You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ar...@apache.org on 2012/07/30 08:39:38 UTC
svn commit: r1367002 [4/21] - in /subversion/branches/svn-bisect: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/
contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/ notes/
notes/api-errata/1.7/ notes/http-and-webdav/ ...
Modified: subversion/branches/svn-bisect/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/include/svn_ra.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/include/svn_ra.h (original)
+++ subversion/branches/svn-bisect/subversion/include/svn_ra.h Mon Jul 30 06:39:28 2012
@@ -1406,8 +1406,9 @@ svn_ra_do_diff(svn_ra_session_t *session
*
* If @a discover_changed_paths, then each call to @a receiver passes a
* <tt>const apr_hash_t *</tt> for the receiver's @a changed_paths argument;
- * the hash's keys are all the paths committed in that revision.
- * Otherwise, each call to receiver passes NULL for @a changed_paths.
+ * the hash's keys are all the paths committed in that revision, the hash's
+ * values are <tt>const svn_log_changed_path2_t *</tt> for each committed
+ * path. Otherwise, each call to receiver passes NULL for @a changed_paths.
*
* If @a strict_node_history is set, copy history will not be traversed
* (if any exists) when harvesting the revision logs for each path.
Modified: subversion/branches/svn-bisect/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/include/svn_repos.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/include/svn_repos.h (original)
+++ subversion/branches/svn-bisect/subversion/include/svn_repos.h Mon Jul 30 06:39:28 2012
@@ -516,8 +516,30 @@ svn_repos_fs(svn_repos_t *repos);
* source filesystem as part of the copy operation; currently, this
* means deleting copied, unused logfiles for a Berkeley DB source
* repository.
+ *
+ * If @a incremental is TRUE, make an effort to not re-copy information
+ * already present in the destination. If incremental hotcopy is not
+ * implemented by the filesystem backend, raise SVN_ERR_UNSUPPORTED_FEATURE.
+ *
+ * @since New in 1.8.
*/
svn_error_t *
+svn_repos_hotcopy2(const char *src_path,
+ const char *dst_path,
+ svn_boolean_t clean_logs,
+ svn_boolean_t incremental,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool);
+
+/**
+ * Like svn_repos_hotcopy2(), but without the @a incremental parameter
+ * and without cancellation support.
+ *
+ * @deprecated Provided for backward compatibility with the 1.6 API.
+ */
+SVN_DEPRECATED
+svn_error_t *
svn_repos_hotcopy(const char *src_path,
const char *dst_path,
svn_boolean_t clean_logs,
@@ -742,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);
+
/** @} */
/* ---------------------------------------------------------------*/
@@ -2994,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/svn-bisect/subversion/include/svn_string.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/include/svn_string.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/include/svn_string.h (original)
+++ subversion/branches/svn-bisect/subversion/include/svn_string.h Mon Jul 30 06:39:28 2012
@@ -383,6 +383,20 @@ svn_boolean_t
svn_cstring_match_list(const char *str, const apr_array_header_t *list);
/**
+ * Get the next token from @a *str interpreting any char from @a sep as a
+ * token separator. Separators at the beginning of @a str will be skipped.
+ * Returns a pointer to the beginning of the first token in @a *str or NULL
+ * if no token is left. Modifies @a str such that the next call will return
+ * the next token.
+ *
+ * Note that the content of @a *str may be modified by this function.
+ *
+ * @since New in 1.8.
+ */
+char *
+svn_cstring_tokenize(const char *sep, char **str);
+
+/**
* Return the number of line breaks in @a msg, allowing any kind of newline
* termination (CR, LF, CRLF, or LFCR), even inconsistent.
*
Modified: subversion/branches/svn-bisect/subversion/include/svn_utf.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/include/svn_utf.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/include/svn_utf.h (original)
+++ subversion/branches/svn-bisect/subversion/include/svn_utf.h Mon Jul 30 06:39:28 2012
@@ -49,12 +49,28 @@ extern "C" {
* Initialize the UTF-8 encoding/decoding routines.
* Allocate cached translation handles in a subpool of @a pool.
*
+ * If @a assume_native_utf8 is TRUE, the native character set is
+ * assumed to be UTF-8, i.e. conversion is a no-op. This is useful
+ * in contexts where the native character set is ASCII but UTF-8
+ * should be used regardless (e.g. for mod_dav_svn which runs within
+ * httpd and always uses the "C" locale).
+ *
* @note It is optional to call this function, but if it is used, no other
* svn function may be in use in other threads during the call of this
* function or when @a pool is cleared or destroyed.
* Initializing the UTF-8 routines will improve performance.
*
- * @since New in 1.1.
+ * @since New in 1.8.
+ */
+void
+svn_utf_initialize2(apr_pool_t *pool,
+ svn_boolean_t assume_native_utf8);
+
+/**
+ * Like svn_utf_initialize but without the ability to force the
+ * native encoding to UTF-8.
+ *
+ * @deprecated Provided for backward compatibility with the 1.7 API.
*/
void
svn_utf_initialize(apr_pool_t *pool);
Modified: subversion/branches/svn-bisect/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/include/svn_wc.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/include/svn_wc.h (original)
+++ subversion/branches/svn-bisect/subversion/include/svn_wc.h Mon Jul 30 06:39:28 2012
@@ -1354,7 +1354,9 @@ typedef struct svn_wc_notify_t {
* In all other cases, it is @c NULL. @since New in 1.5 */
const char *changelist_name;
- /** When @c action is #svn_wc_notify_merge_begin, and both the
+ /** When @c action is #svn_wc_notify_merge_begin or
+ * #svn_wc_notify_foreign_merge_begin or
+ * #svn_wc_notify_merge_record_info_begin, and both the
* left and right sides of the merge are from the same URL. In all
* other cases, it is @c NULL. @since New in 1.5 */
svn_merge_range_t *merge_range;
@@ -4047,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
@@ -4108,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,
@@ -5485,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.
*
@@ -5558,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,
@@ -5689,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"
@@ -5699,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,
@@ -6136,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.
@@ -6189,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/svn-bisect/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c Mon Jul 30 06:39:28 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/svn-bisect/subversion/libsvn_auth_kwallet/kwallet.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_auth_kwallet/kwallet.cpp?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_auth_kwallet/kwallet.cpp (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_auth_kwallet/kwallet.cpp Mon Jul 30 06:39:28 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/svn-bisect/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/add.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/add.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/add.c Mon Jul 30 06:39:28 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"
@@ -809,6 +810,11 @@ mkdir_urls(const apr_array_header_t *url
const char *bname;
svn_uri_split(&common, &bname, common, pool);
APR_ARRAY_PUSH(targets, const char *) = bname;
+
+ if (*bname == '\0')
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("There is no valid uri above '%s'"),
+ common);
}
else
{
@@ -831,6 +837,12 @@ mkdir_urls(const apr_array_header_t *url
const char *bname;
svn_uri_split(&common, &bname, common, pool);
+
+ if (*bname == '\0')
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("There is no valid uri above '%s'"),
+ common);
+
for (i = 0; i < targets->nelts; i++)
{
const char *path = APR_ARRAY_IDX(targets, i, const char *);
@@ -885,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/svn-bisect/subversion/libsvn_client/checkout.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/checkout.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/checkout.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/checkout.c Mon Jul 30 06:39:28 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/svn-bisect/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/client.h?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/client.h (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/client.h Mon Jul 30 06:39:28 2012
@@ -148,7 +148,9 @@ svn_client__repos_locations(const char *
*
* Set *OP_URL to the URL that the object PEG_URL@PEG_REVNUM had in
* revision OP_REVNUM.
- * RA_SESSION is required. */
+ *
+ * RA_SESSION is an open RA session to the correct repository; it may be
+ * temporarily reparented inside this function. */
svn_error_t *
svn_client__repos_location(const char **start_url,
svn_ra_session_t *ra_session,
@@ -161,8 +163,8 @@ svn_client__repos_location(const char **
/* Set *SEGMENTS to an array of svn_location_segment_t * objects, each
- representing a reposition location segment for the history of PATH
- (which is relative to RA_SESSION's session URL) in PEG_REVISION
+ representing a reposition location segment for the history of URL
+ in PEG_REVISION
between END_REVISION and START_REVISION, ordered from oldest
segment to youngest. *SEGMENTS may be empty but it will never
be NULL.
@@ -171,13 +173,16 @@ svn_client__repos_location(const char **
svn_ra_get_location_segments() interface, which see for the rules
governing PEG_REVISION, START_REVISION, and END_REVISION.
+ RA_SESSION is an RA session open to the repository of URL; it may be
+ temporarily reparented within this function.
+
CTX is the client context baton.
Use POOL for all allocations. */
svn_error_t *
svn_client__repos_location_segments(apr_array_header_t **segments,
svn_ra_session_t *ra_session,
- const char *path,
+ const char *url,
svn_revnum_t peg_revision,
svn_revnum_t start_revision,
svn_revnum_t end_revision,
@@ -185,19 +190,30 @@ svn_client__repos_location_segments(apr_
apr_pool_t *pool);
-/* Set *ANCESTOR_PATH and *ANCESTOR_REVISION to the youngest common
- ancestor path (a path relative to the root of the repository) and
- revision, respectively, of the two locations identified as
- PATH_OR_URL1@REV1 and PATH_OR_URL2@REV1. Use the authentication
- baton cached in CTX to authenticate against the repository.
- This function assumes that PATH_OR_URL1@REV1 and PATH_OR_URL2@REV1
- both refer to the same repository. Use POOL for all allocations. */
+/* Find the common ancestor of two locations in a repository.
+ Ancestry is determined by the 'copy-from' relationship and the normal
+ successor relationship.
+
+ Set *ANCESTOR_RELPATH, *ANCESTOR_URL, and *ANCESTOR_REVISION to the
+ path (relative to the root of the repository, with no leading '/'),
+ URL, and revision, respectively, of the youngest common ancestor of
+ the two locations URL1@REV1 and URL2@REV2. Set *ANCESTOR_RELPATH and
+ *ANCESTOR_URL to NULL and *ANCESTOR_REVISION to SVN_INVALID_REVNUM if
+ they have no common ancestor. This function assumes that URL1@REV1
+ and URL2@REV2 both refer to the same repository.
+
+ Use the authentication baton cached in CTX to authenticate against
+ the repository. Use POOL for all allocations.
+
+ See also svn_client__youngest_common_ancestor().
+*/
svn_error_t *
-svn_client__get_youngest_common_ancestor(const char **ancestor_path,
+svn_client__get_youngest_common_ancestor(const char **ancestor_relpath,
+ const char **ancestor_url,
svn_revnum_t *ancestor_revision,
- const char *path_or_url1,
+ const char *url1,
svn_revnum_t rev1,
- const char *path_or_url2,
+ const char *url2,
svn_revnum_t rev2,
svn_client_ctx_t *ctx,
apr_pool_t *pool);
@@ -238,11 +254,10 @@ svn_client__ra_session_from_path(svn_ra_
apr_pool_t *pool);
/* Ensure that RA_SESSION's session URL matches SESSION_URL,
- reparenting that session if necessary. If reparenting occurs,
- store the previous session URL in *OLD_SESSION_URL (so that if the
+ reparenting that session if necessary.
+ Store the previous session URL in *OLD_SESSION_URL (so that if the
reparenting is meant to be temporary, the caller can reparent the
- session back to where it was); otherwise set *OLD_SESSION_URL to
- NULL.
+ session back to where it was).
If SESSION_URL is NULL, treat this as a magic value meaning "point
the RA session to the root of the repository".
@@ -257,8 +272,7 @@ svn_client__ra_session_from_path(svn_ra_
[...]
- if (old_session_url)
- SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
+ SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
*/
svn_error_t *
svn_client__ensure_ra_session_url(const char **old_session_url,
@@ -485,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.
@@ -551,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,
@@ -1090,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/svn-bisect/subversion/libsvn_client/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/cmdline.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/cmdline.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/cmdline.c Mon Jul 30 06:39:28 2012
@@ -168,7 +168,6 @@ svn_client_args_to_target_array2(apr_arr
int i;
svn_boolean_t rel_url_found = FALSE;
const char *root_url = NULL;
- svn_error_t *err = SVN_NO_ERROR;
apr_array_header_t *input_targets =
apr_array_make(pool, DEFAULT_ARRAY_SIZE, sizeof(const char *));
apr_array_header_t *output_targets =
@@ -348,6 +347,7 @@ svn_client_args_to_target_array2(apr_arr
if (root_url == NULL)
{
const char *current_abspath;
+ svn_error_t *err;
SVN_ERR(svn_dirent_get_absolute(¤t_abspath, "", pool));
err = svn_client_get_repos_root(&root_url, NULL /* uuid */,
@@ -391,11 +391,17 @@ svn_client_args_to_target_array2(apr_arr
else
*targets_p = output_targets;
- if (reserved_names && ! err)
- for (i = 0; i < reserved_names->nelts; ++i)
- err = svn_error_createf(SVN_ERR_RESERVED_FILENAME_SPECIFIED, err,
- _("'%s' ends in a reserved name"),
- APR_ARRAY_IDX(reserved_names, i, const char *));
+ if (reserved_names)
+ {
+ svn_error_t *err = SVN_NO_ERROR;
+
+ for (i = 0; i < reserved_names->nelts; ++i)
+ err = svn_error_createf(SVN_ERR_RESERVED_FILENAME_SPECIFIED, err,
+ _("'%s' ends in a reserved name"),
+ APR_ARRAY_IDX(reserved_names, i,
+ const char *));
+ return svn_error_trace(err);
+ }
- return svn_error_trace(err);
+ return SVN_NO_ERROR;
}
Modified: subversion/branches/svn-bisect/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/commit.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/commit.c Mon Jul 30 06:39:28 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"
@@ -145,19 +146,22 @@ send_file_contents(const char *path,
if (svn_subst_translation_required(eol_style, eol, keywords,
FALSE, TRUE))
{
- svn_boolean_t repair = FALSE;
+ if (eol_style == svn_subst_eol_style_unknown)
+ return svn_error_createf(SVN_ERR_IO_UNKNOWN_EOL, NULL,
+ _("%s property on '%s' contains "
+ "unrecognized EOL-style '%s'"),
+ SVN_PROP_EOL_STYLE, path,
+ eol_style_val->data);
+ /* We're importing, so translate files with 'native' eol-style to
+ * repository-normal form, not to this platform's native EOL. */
if (eol_style == svn_subst_eol_style_native)
eol = SVN_SUBST_NATIVE_EOL_STR;
- else if (eol_style == svn_subst_eol_style_fixed)
- repair = TRUE;
- else if (eol_style != svn_subst_eol_style_none)
- return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL);
/* Wrap the working copy stream with a filter to detranslate it. */
contents = svn_subst_stream_translated(contents,
eol,
- repair,
+ TRUE /* repair */,
keywords,
FALSE /* expand */,
pool);
@@ -642,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,
@@ -666,7 +671,22 @@ get_ra_editor(svn_ra_session_t **ra_sess
SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
log_msg, ctx, pool));
+ /* We need this for the shims. */
+ if (base_dir_abspath)
+ {
+ const char *relpath;
+
+ SVN_ERR(svn_ra_get_path_relative_to_root(*ra_session, &relpath, base_url,
+ pool));
+ anchor_abspath = svn_dirent_join(base_dir_abspath, relpath, pool);
+ }
+ else
+ 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,
@@ -822,7 +842,7 @@ svn_client_import4(const char *path,
ignore_unknown_node_types, ctx, subpool)))
{
svn_error_clear(editor->abort_edit(edit_baton, subpool));
- return err;
+ return svn_error_trace(err);
}
svn_pool_destroy(subpool);
Modified: subversion/branches/svn-bisect/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/commit_util.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/commit_util.c Mon Jul 30 06:39:28 2012
@@ -416,6 +416,10 @@ bail_on_tree_conflicted_ancestor(svn_wc_
by recursing deeper into a dir target. (This is used to skip all file
externals that aren't explicit commit targets.)
+ DANGLERS is a hash table mapping const char* absolute paths of a parent
+ 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.
@@ -435,6 +439,7 @@ harvest_committables(svn_wc_context_t *w
svn_boolean_t skip_files,
svn_boolean_t skip_dirs,
svn_boolean_t is_explicit_target,
+ apr_hash_t *danglers,
svn_client__check_url_kind_t check_url_func,
void *check_url_baton,
svn_cancel_func_t cancel_func,
@@ -627,7 +632,7 @@ harvest_committables(svn_wc_context_t *w
/* Determine from what parent we would be the deleted child */
SVN_ERR(svn_wc__node_get_origin(NULL, &revision, &repos_relpath,
- NULL, NULL, wc_ctx,
+ NULL, NULL, NULL, wc_ctx,
svn_dirent_dirname(local_abspath,
scratch_pool),
FALSE, scratch_pool, scratch_pool));
@@ -684,7 +689,7 @@ harvest_committables(svn_wc_context_t *w
SVN_ERR(svn_wc__node_get_origin(NULL, &cf_rev,
&cf_relpath, NULL,
- NULL,
+ NULL, NULL,
wc_ctx, local_abspath, FALSE,
scratch_pool, scratch_pool));
@@ -814,6 +819,45 @@ harvest_committables(svn_wc_context_t *w
}
}
+ /* Make sure we check for dangling children on additions */
+ if (state_flags && is_added && is_explicit_target && danglers)
+ {
+ /* If a node is added, it's parent must exist in the repository at the
+ time of committing */
+
+ svn_boolean_t parent_added;
+ const char *parent_abspath = svn_dirent_dirname(local_abspath,
+ scratch_pool);
+
+ SVN_ERR(svn_wc__node_is_added(&parent_added, wc_ctx, parent_abspath,
+ scratch_pool));
+
+ if (parent_added)
+ {
+ const char *copy_root_abspath;
+ svn_boolean_t parent_is_copy;
+
+ /* 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, ©_root_abspath,
+ wc_ctx, parent_abspath,
+ FALSE, scratch_pool, scratch_pool));
+
+ if (parent_is_copy)
+ parent_abspath = copy_root_abspath;
+
+ if (!apr_hash_get(danglers, parent_abspath, APR_HASH_KEY_STRING))
+ {
+ apr_hash_set(danglers,
+ apr_pstrdup(result_pool, parent_abspath),
+ APR_HASH_KEY_STRING,
+ apr_pstrdup(result_pool, local_abspath));
+ }
+ }
+ }
+
if (db_kind != svn_node_dir || depth <= svn_depth_empty)
return SVN_NO_ERROR;
@@ -863,6 +907,7 @@ harvest_committables(svn_wc_context_t *w
(depth < svn_depth_files),
(depth < svn_depth_immediates),
FALSE, /* IS_EXPLICIT_TARGET */
+ danglers,
check_url_func, check_url_baton,
cancel_func, cancel_baton,
notify_func, notify_baton,
@@ -1032,13 +1077,13 @@ svn_client__harvest_committables(svn_cli
* Since we don't know what's included in the commit until we've
* harvested all the targets, we can't reliably check this as we
* go. So in `danglers', we record named targets whose parents
- * are unversioned, then after harvesting the total commit group, we
- * check to make sure those parents are included.
+ * do not yet exist in the repository. Then after harvesting the total
+ * commit group, we check to make sure those parents are included.
*
- * Each key of danglers is an unversioned parent. The (const char *)
- * value is one of that parent's children which is named as part of
- * the commit; the child is included only to make a better error
- * message.
+ * Each key of danglers is a parent which does not exist in the
+ * repository. The (const char *) value is one of that parent's
+ * children which is named as part of the commit; the child is
+ * included only to make a better error message.
*
* (The reason we don't bother to check unnamed -- i.e, implicit --
* targets is that they can only join the commit if their parents
@@ -1063,10 +1108,8 @@ svn_client__harvest_committables(svn_cli
for (i = 0; i < targets->nelts; ++i)
{
const char *target_abspath;
- svn_boolean_t is_added;
svn_node_kind_t kind;
const char *repos_root_url;
- svn_error_t *err;
svn_pool_clear(iterpool);
@@ -1103,35 +1146,6 @@ svn_client__harvest_committables(svn_cli
target_abspath,
result_pool, iterpool));
- /* Handle an added/replaced node. */
- SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, target_abspath,
- iterpool));
- if (is_added)
- {
- /* This node is added. Is the parent also added? */
- const char *parent_abspath = svn_dirent_dirname(target_abspath,
- iterpool);
- err = svn_wc__node_is_added(&is_added, ctx->wc_ctx, parent_abspath,
- iterpool);
- if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_createf(
- SVN_ERR_WC_CORRUPT, err,
- _("'%s' is scheduled for addition within unversioned parent"),
- svn_dirent_local_style(target_abspath, iterpool));
- SVN_ERR(err);
-
- if (is_added)
- {
- /* Copy the parent and target into pool; iterpool
- lasts only for this loop iteration, and we check
- danglers after the loop is over. */
- apr_hash_set(danglers,
- apr_pstrdup(scratch_pool, parent_abspath),
- APR_HASH_KEY_STRING,
- apr_pstrdup(scratch_pool, target_abspath));
- }
- }
-
/* Handle our TARGET. */
/* Make sure this isn't inside a working copy subtree that is
* marked as tree-conflicted. */
@@ -1148,6 +1162,7 @@ svn_client__harvest_committables(svn_cli
depth, just_locked, changelist_hash,
FALSE, FALSE,
TRUE /* IS_EXPLICIT_TARGET */,
+ danglers,
check_url_func, check_url_baton,
ctx->cancel_func, ctx->cancel_baton,
ctx->notify_func2, ctx->notify_baton2,
@@ -1170,31 +1185,31 @@ svn_client__harvest_committables(svn_cli
svn_pool_clear(iterpool);
- if (! look_up_committable(*committables, dangling_parent, iterpool))
- {
- const char *dangling_child = svn__apr_hash_index_val(hi);
-
- if (ctx->notify_func2 != NULL)
- {
- svn_wc_notify_t *notify;
-
- notify = svn_wc_create_notify(dangling_child,
- svn_wc_notify_failed_no_parent,
- scratch_pool);
-
- ctx->notify_func2(ctx->notify_baton2, notify, iterpool);
- }
-
- return svn_error_createf(
- SVN_ERR_ILLEGAL_TARGET, NULL,
- _("'%s' is not under version control "
- "and is not part of the commit, "
- "yet its child '%s' is part of the commit"),
- /* Probably one or both of these is an entry, but
- safest to local_stylize just in case. */
- svn_dirent_local_style(dangling_parent, iterpool),
- svn_dirent_local_style(dangling_child, iterpool));
- }
+ if (! look_up_committable(*committables, dangling_parent, iterpool))
+ {
+ const char *dangling_child = svn__apr_hash_index_val(hi);
+
+ if (ctx->notify_func2 != NULL)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(dangling_child,
+ svn_wc_notify_failed_no_parent,
+ scratch_pool);
+
+ ctx->notify_func2(ctx->notify_baton2, notify, iterpool);
+ }
+
+ return svn_error_createf(
+ SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not known to exist in the repository "
+ "and is not part of the commit, "
+ "yet its child '%s' is part of the commit"),
+ /* Probably one or both of these is an entry, but
+ safest to local_stylize just in case. */
+ svn_dirent_local_style(dangling_parent, iterpool),
+ svn_dirent_local_style(dangling_child, iterpool));
+ }
}
svn_pool_destroy(iterpool);
@@ -1242,6 +1257,7 @@ harvest_copy_committables(void *baton, v
NULL,
FALSE, FALSE, /* skip files, dirs */
TRUE, /* IS_EXPLICIT_TARGET (don't care) */
+ NULL,
btn->check_url_func,
btn->check_url_baton,
btn->ctx->cancel_func,
Modified: subversion/branches/svn-bisect/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/copy.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/copy.c Mon Jul 30 06:39:28 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"
@@ -98,7 +99,7 @@ calculate_target_mergeinfo(svn_ra_sessio
SVN_ERR(svn_wc__node_get_origin(NULL, &src_revnum,
&repos_relpath, &repos_root_url,
- NULL,
+ NULL, NULL,
ctx->wc_ctx, local_abspath, FALSE,
pool, pool));
@@ -113,20 +114,11 @@ calculate_target_mergeinfo(svn_ra_sessio
if (! locally_added)
{
- /* Fetch any existing (explicit) mergeinfo. We'll temporarily
- reparent to the target URL here, just to keep the code simple.
- We could, as an alternative, first see if the target URL was a
- child of the session URL and use the relative "remainder",
- falling back to this reparenting as necessary. */
- const char *old_session_url = NULL;
- SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
- ra_session, src_url, pool));
+ /* Fetch any existing (explicit) mergeinfo. */
SVN_ERR(svn_client__get_repos_mergeinfo(&src_mergeinfo, ra_session,
- "", src_revnum,
+ src_url, src_revnum,
svn_mergeinfo_inherited,
TRUE, pool));
- if (old_session_url)
- SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
}
*target_mergeinfo = src_mergeinfo;
@@ -981,7 +973,7 @@ repos_to_repos_copy(const apr_array_head
}
else
{
- const char *old_url = NULL;
+ const char *old_url;
src_rel = NULL;
SVN_ERR_ASSERT(! is_move);
@@ -1098,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,
@@ -1410,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,
@@ -1512,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);
@@ -1567,27 +1565,18 @@ repos_to_wc_copy_single(svn_client__copy
else if (pair->src_kind == svn_node_file)
{
- svn_stream_t *fstream;
- const char *new_text_path;
apr_hash_t *new_props;
const char *src_rel;
- svn_stream_t *new_base_contents;
-
- SVN_ERR(svn_stream_open_unique(&fstream, &new_text_path, NULL,
- svn_io_file_del_on_pool_cleanup, pool,
- pool));
+ svn_stream_t *new_base_contents = svn_stream_buffered(pool);
SVN_ERR(svn_ra_get_path_relative_to_session(ra_session, &src_rel,
pair->src_abspath_or_url,
pool));
/* Fetch the file content. While doing so, resolve pair->src_revnum
* to an actual revision number if it's 'invalid' meaning 'head'. */
- SVN_ERR(svn_ra_get_file(ra_session, src_rel, pair->src_revnum, fstream,
+ SVN_ERR(svn_ra_get_file(ra_session, src_rel, pair->src_revnum,
+ new_base_contents,
&pair->src_revnum, &new_props, pool));
- SVN_ERR(svn_stream_close(fstream));
-
- SVN_ERR(svn_stream_open_readonly(&new_base_contents, new_text_path,
- pool, pool));
SVN_ERR(svn_wc_add_repos_file4(
ctx->wc_ctx, dst_abspath,
new_base_contents, NULL, new_props, NULL,
@@ -2127,7 +2116,7 @@ try_copy(const apr_array_header_t *sourc
SVN_ERR(svn_wc__node_get_origin(NULL, ©from_rev,
©from_repos_relpath,
©from_repos_root_url,
- NULL,
+ NULL, NULL,
ctx->wc_ctx,
pair->src_abspath_or_url,
TRUE, iterpool, iterpool));
Modified: subversion/branches/svn-bisect/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/delete.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/delete.c Mon Jul 30 06:39:28 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,
@@ -272,6 +276,12 @@ delete_urls_multi_repos(const apr_array_
APR_ARRAY_PUSH(relpaths_list, const char *) = repos_relpath;
}
+ /* Check we identified a non-root relpath. Return an RA error
+ code for 1.6 compatibility. */
+ if (!repos_relpath || !*repos_relpath)
+ return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+ "URL '%s' not within a repository", uri);
+
/* Now, test to see if the thing actually exists. */
SVN_ERR(svn_ra_check_path(ra_session, repos_relpath, SVN_INVALID_REVNUM,
&kind, pool));
Modified: subversion/branches/svn-bisect/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/deprecated.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/deprecated.c Mon Jul 30 06:39:28 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/svn-bisect/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/diff.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/diff.c Mon Jul 30 06:39:28 2012
@@ -147,18 +147,25 @@ display_mergeinfo_diff(const char *old_m
If TOKEN is empty, or is already terminated by an EOL marker,
return TOKEN unmodified. Else, return a new string consisting
of the concatenation of TOKEN and the system's default EOL marker.
- The new string is allocated from POOL. */
+ The new string is allocated from POOL.
+ If HAD_EOL is not NULL, indicate in *HAD_EOL if the token had a EOL. */
static const svn_string_t *
-maybe_append_eol(const svn_string_t *token, apr_pool_t *pool)
+maybe_append_eol(const svn_string_t *token, svn_boolean_t *had_eol,
+ apr_pool_t *pool)
{
const char *curp;
+ if (had_eol)
+ *had_eol = FALSE;
+
if (token->len == 0)
return token;
curp = token->data + token->len - 1;
if (*curp == '\r')
{
+ if (had_eol)
+ *had_eol = TRUE;
return token;
}
else if (*curp != '\n')
@@ -167,6 +174,8 @@ maybe_append_eol(const svn_string_t *tok
}
else
{
+ if (had_eol)
+ *had_eol = TRUE;
return token;
}
}
@@ -665,18 +674,19 @@ display_prop_diffs(const apr_array_heade
const svn_string_t *tmp;
const svn_string_t *orig;
const svn_string_t *val;
+ svn_boolean_t val_has_eol;
/* The last character in a property is often not a newline.
- Since the diff is not useful anyway for patching properties an
- eol character is appended when needed to remove those pescious
- ' \ No newline at end of file' lines. */
+ 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 property' manually if needed. */
tmp = original_value ? original_value
: svn_string_create_empty(iterpool);
- orig = maybe_append_eol(tmp, iterpool);
+ orig = maybe_append_eol(tmp, NULL, iterpool);
tmp = propchange->value ? propchange->value :
svn_string_create_empty(iterpool);
- val = maybe_append_eol(tmp, iterpool);
+ val = maybe_append_eol(tmp, &val_has_eol, iterpool);
SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options,
iterpool));
@@ -695,7 +705,12 @@ display_prop_diffs(const apr_array_heade
svn_dirent_local_style(path,
iterpool),
encoding, orig, val, iterpool));
-
+ if (!val_has_eol)
+ {
+ const char *s = "\\ No newline at end of property" APR_EOL_STR;
+ apr_size_t len = strlen(s);
+ SVN_ERR(svn_stream_write(outstream, s, &len));
+ }
}
}
svn_pool_destroy(iterpool);
@@ -762,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;
@@ -802,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));
@@ -1592,7 +1614,7 @@ diff_prepare_repos_repos(const char **ur
*url1, *rev1, *rev2);
else
return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
- _("Diff targets '%s and '%s' were not found "
+ _("Diff targets '%s' and '%s' were not found "
"in the repository at revisions '%ld' and "
"'%ld'"),
*url1, *url2, *rev1, *rev2);
@@ -1988,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,
@@ -2398,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,
@@ -2427,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;
@@ -2455,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,
@@ -2480,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/svn-bisect/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/export.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/export.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/export.c Mon Jul 30 06:39:28 2012
@@ -402,7 +402,7 @@ copy_versioned_files(const char *from_ab
const char *repos_relpath;
SVN_ERR(svn_wc__node_get_origin(&is_added, NULL, &repos_relpath,
- NULL, NULL,
+ NULL, NULL, NULL,
ctx->wc_ctx, from_abspath, FALSE,
pool, pool));
@@ -1020,6 +1020,55 @@ close_file(void *file_baton,
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)
+{
+ /* We know the root of the edit is a directory. */
+ if (path[0] == '\0')
+ *kind = svn_kind_dir;
+
+ /* ### TODO: We could possibly fetch the kind of the object in question
+ from the server with a second ra_session, but right now this
+ seems to work. */
+ else
+ *kind = svn_kind_unknown;
+
+ 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)
+{
+ /* Always use empty props, since the node won't have pre-existing props
+ (This is an export, remember?) */
+ *props = apr_hash_make(result_pool);
+
+ 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)
+{
+ /* An export always gets text against the empty stream (i.e, full texts). */
+ *filename = NULL;
+
+ return SVN_NO_ERROR;
+}
+
/*** Public Interfaces ***/
@@ -1180,6 +1229,11 @@ svn_client_export5(svn_revnum_t *result_
&edit_baton,
pool));
+ shim_callbacks->fetch_kind_func = fetch_kind_func;
+ shim_callbacks->fetch_props_func = fetch_props_func;
+ shim_callbacks->fetch_base_func = fetch_base_func;
+ shim_callbacks->fetch_baton = eb;
+
SVN_ERR(svn_editor__insert_shims(&export_editor, &edit_baton,
export_editor, edit_baton,
shim_callbacks, pool, pool));
Modified: subversion/branches/svn-bisect/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/externals.c?rev=1367002&r1=1367001&r2=1367002&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_client/externals.c Mon Jul 30 06:39:28 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;