You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pr...@apache.org on 2013/02/13 11:21:36 UTC
svn commit: r1445542 [2/16] - in /subversion/branches/verify-keep-going: ./
build/generator/ build/generator/swig/ build/generator/templates/
build/win32/ contrib/server-side/fsfsfixer/fixer/
contrib/server-side/svncutter/ notes/ notes/api-errata/1.7/ ...
Modified: subversion/branches/verify-keep-going/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/include/private/svn_wc_private.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/include/private/svn_wc_private.h (original)
+++ subversion/branches/verify-keep-going/subversion/include/private/svn_wc_private.h Wed Feb 13 10:21:33 2013
@@ -302,6 +302,12 @@ svn_wc__get_tree_conflict(const svn_wc_c
/** Record the tree conflict described by @a conflict in the WC for
* @a conflict->local_abspath. Use @a scratch_pool for all temporary
* allocations.
+ *
+ * Returns an SVN_ERR_WC_PATH_UNEXPECTED_STATUS error when
+ * CONFLICT->LOCAL_ABSPATH is already tree conflicted.
+ *
+ * ### This function can't set moved_away, moved_here conflicts for
+ * any operation, except merges.
*/
svn_error_t *
svn_wc__add_tree_conflict(svn_wc_context_t *wc_ctx,
@@ -415,18 +421,21 @@ svn_wc__node_get_children(const apr_arra
/**
- * Fetch the repository root information for the working version
- * of the node at @a local_abspath into @a *repos_root_url
- * and @a *repos_uuid. Use @a wc_ctx to access the working copy
- * for @a local_abspath, @a scratch_pool for all temporary allocations,
- * @a result_pool for result allocations. Note: the results will be NULL if
- * the node does not exist or is not under version control. If the node is
- * locally added, return the repository root it will have if committed.
+ * Fetch the repository information for the working version
+ * of the node at @a local_abspath into @a *revision, @a *repos_relpath,
+ * @a *repos_root_url and @a *repos_uuid. Use @a wc_ctx to access the working
+ * copy. Allocate results in @a result_pool.
*
- * Either output argument may be NULL, indicating no interest.
+ * @a *revision will be set to SVN_INVALID_REVNUM for any shadowed node (including
+ * added and deleted nodes). All other output values will be set to the current
+ * values or those they would have after a commit.
+ *
+ * All output argument may be NULL, indicating no interest.
*/
svn_error_t *
-svn_wc__node_get_repos_info(const char **repos_root_url,
+svn_wc__node_get_repos_info(svn_revnum_t *revision,
+ const char **repos_relpath,
+ const char **repos_root_url,
const char **repos_uuid,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
@@ -517,22 +526,6 @@ svn_wc__node_get_origin(svn_boolean_t *i
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
-
-/**
- * Set @a *repos_relpath to the corresponding repos_relpath for @a
- * local_abspath, using @a wc_ctx. If the node is added, return the
- * repos_relpath it will have in the repository.
- *
- * If @a local_abspath is not in the working copy, return @c
- * SVN_ERR_WC_PATH_NOT_FOUND.
- * */
-svn_error_t *
-svn_wc__node_get_repos_relpath(const char **repos_relpath,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
-
/**
* Set @a *is_deleted to TRUE if @a local_abspath is deleted, using
* @a wc_ctx. If @a local_abspath is not in the working copy, return
@@ -620,14 +613,14 @@ svn_wc__node_has_working(svn_boolean_t *
/**
* Get the repository location of the base node at @a local_abspath.
*
- * Set *REVISION, *REPOS_RELPATH, *REPOS_ROOT_URL and *REPOS_UUID to the
- * location that this node was checked out at or last updated/switched to,
- * regardless of any uncommitted changes (delete, replace and/or
- * copy-here/move-here).
+ * Set *REVISION, *REPOS_RELPATH, *REPOS_ROOT_URL *REPOS_UUID and *LOCK_TOKEN
+ * to the location that this node was checked out at or last updated/switched
+ * to, regardless of any uncommitted changes (delete, replace and/or copy-here/
+ * move-here).
*
* If there is no base node at @a local_abspath (such as when there is a
* locally added/copied/moved-here node that is not part of a replace),
- * return @c SVN_INVALID_REVNUM/NULL/NULL/NULL.
+ * return @c SVN_INVALID_REVNUM/NULL/NULL/NULL/NULL.
*
* All output arguments may be NULL.
*
@@ -639,6 +632,7 @@ svn_wc__node_get_base(svn_revnum_t *revi
const char **repos_relpath,
const char **repos_root_url,
const char **repos_uuid,
+ const char **lock_token,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
apr_pool_t *result_pool,
@@ -679,30 +673,6 @@ svn_wc__node_get_pre_ng_status_data(svn_
apr_pool_t *scratch_pool);
/**
- * Fetch lock information (if any) for @a local_abspath using @a wc_ctx:
- *
- * Set @a *lock_token to the lock token (or NULL)
- * Set @a *lock_owner to the owner of the lock (or NULL)
- * Set @a *lock_comment to the comment associated with the lock (or NULL)
- * Set @a *lock_date to the timestamp of the lock (or 0)
- *
- * Any of the aforementioned return values may be NULL to indicate
- * that the caller doesn't care about those values.
- *
- * If @a local_abspath is not in the working copy, return @c
- * SVN_ERR_WC_PATH_NOT_FOUND.
- */
-svn_error_t *
-svn_wc__node_get_lock_info(const char **lock_token,
- const char **lock_owner,
- const char **lock_comment,
- apr_time_t *lock_date,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
-
-/**
* Acquire a recursive write lock for @a local_abspath. If @a lock_anchor
* is true, determine if @a local_abspath has an anchor that should be locked
* instead; otherwise, @a local_abspath must be a versioned directory.
@@ -1111,6 +1081,12 @@ svn_wc__get_not_present_descendants(cons
* If DELETED is not NULL, set *DELETED to TRUE if the node is marked as
* deleted in the working copy.
*
+ * If EXCLUDED is not NULL, set *EXCLUDED to TRUE if the node is marked as
+ * user or server excluded.
+ *
+ * If PARENT_DEPTH is not NULL, set *PARENT_DEPTH to the depth stored on the
+ * parent. (Set to svn_depth_unknown if LOCAL_ABSPATH itself exists as node)
+ *
* All output arguments except OBSTRUCTION_STATE can be NULL to ommit the
* result.
*
@@ -1120,6 +1096,8 @@ svn_error_t *
svn_wc__check_for_obstructions(svn_wc_notify_state_t *obstruction_state,
svn_node_kind_t *kind,
svn_boolean_t *deleted,
+ svn_boolean_t *excluded,
+ svn_depth_t *parent_depth,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_boolean_t no_wcroot_check,
@@ -1712,17 +1690,13 @@ typedef svn_error_t *
apr_pool_t *scratch_pool);
/** Obtains a diff processor that will drive the diff callbacks when it
- * is invoked. The state arguments will be handled by the state processor
- * or ignored if STATE_HANDLER is NULL
+ * is invoked.
*/
svn_error_t *
-svn_wc__wrap_diff_callbacks(svn_diff_tree_processor_t **diff_processor,
+svn_wc__wrap_diff_callbacks(const svn_diff_tree_processor_t **diff_processor,
const svn_wc_diff_callbacks4_t *callbacks,
void *callback_baton,
- svn_wc__diff_state_handle_t state_handle,
- svn_wc__diff_state_close_t state_close,
- svn_wc__diff_state_absent_t state_absent,
- void *state_baton,
+ svn_boolean_t walk_deleted_dirs,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
Modified: subversion/branches/verify-keep-going/subversion/include/svn_auth.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/include/svn_auth.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/include/svn_auth.h (original)
+++ subversion/branches/verify-keep-going/subversion/include/svn_auth.h Wed Feb 13 10:21:33 2013
@@ -590,19 +590,25 @@ svn_auth_get_parameter(svn_auth_baton_t
/** @brief Indicates whether providers may save passwords to disk in
* plaintext. Property value can be either SVN_CONFIG_TRUE,
- * SVN_CONFIG_FALSE, or SVN_CONFIG_ASK. */
+ * SVN_CONFIG_FALSE, or SVN_CONFIG_ASK.
+ * @since New in 1.6.
+ */
#define SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS SVN_AUTH_PARAM_PREFIX \
"store-plaintext-passwords"
/** @brief The application doesn't want any providers to save passphrase
* to disk. Property value is irrelevant; only property's existence
- * matters. */
+ * matters.
+ * @since New in 1.6.
+ */
#define SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP \
SVN_AUTH_PARAM_PREFIX "dont-store-ssl-client-cert-pp"
/** @brief Indicates whether providers may save passphrase to disk in
* plaintext. Property value can be either SVN_CONFIG_TRUE,
- * SVN_CONFIG_FALSE, or SVN_CONFIG_ASK. */
+ * SVN_CONFIG_FALSE, or SVN_CONFIG_ASK.
+ * @since New in 1.6.
+ */
#define SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT \
SVN_AUTH_PARAM_PREFIX "store-ssl-client-cert-pp-plaintext"
@@ -769,6 +775,39 @@ svn_auth_get_simple_provider2(
void *prompt_baton,
apr_pool_t *pool);
+/** Callback for svn_auth_cleanup_walk().
+ *
+ * Called for each credential to allow selectively removing credentials.
+ *
+ * @a cred_kind and @a realmstring specify the key of the credential (see
+ * svn_auth_first_credentials()).
+ *
+ * @a provider specifies which provider currently holds the credential.
+ *
+ * Before returning set @a *delete_cred to TRUE to remove the credential from
+ * the cache.
+ *
+ * @since New in 1.8.
+ */
+typedef svn_error_t * (*svn_auth_cleanup_callback)(svn_boolean_t *delete_cred,
+ void *cleanup_baton,
+ const char *cred_kind,
+ const char *realmstring,
+ const char *provider,
+ apr_pool_t *scratch_pool);
+
+/** Call @a cleanup with information describing each currently cached
+ * credential (in providers that support iterating). If the callback
+ * confirms that the credential should be deleted, delete it.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_auth_cleanup_walk(svn_auth_baton_t *auth_baton,
+ svn_auth_cleanup_callback cleanup,
+ void *cleanup_baton,
+ apr_pool_t *scratch_pool);
+
/** Like svn_auth_get_simple_provider2, but without the ability to
* call the svn_auth_plaintext_prompt_func_t callback, and the provider
* always assumes that it is allowed to store the password in plaintext.
Modified: subversion/branches/verify-keep-going/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/include/svn_client.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/include/svn_client.h (original)
+++ subversion/branches/verify-keep-going/subversion/include/svn_client.h Wed Feb 13 10:21:33 2013
@@ -367,7 +367,7 @@ typedef struct svn_client_proplist_item_
*
* The #svn_prop_inherited_item_t->path_or_url members of the
* #svn_prop_inherited_item_t * structures in @a inherited_props are
- * URLs if @a path is a URL or if @path is a working copy path but the
+ * URLs if @a path is a URL or if @a path is a working copy path but the
* property represented by the structure is above the working copy root (i.e.
* the inherited property is from the cache). In all other cases the
* #svn_prop_inherited_item_t->path_or_url members are absolute working copy
@@ -4264,6 +4264,11 @@ svn_client_resolved(const char *path,
* - #svn_wc_conflict_choose_mine_conflict
* ###...
*
+ * - svn_wc_conflict_choose_unspecified
+ * invoke @a ctx->conflict_func2 with @a ctx->conflict_baton2 to obtain
+ * a resolution decision for each conflict. This can be used to
+ * implement interactive conflict resolution.
+ *
* #svn_wc_conflict_choose_theirs_conflict and
* #svn_wc_conflict_choose_mine_conflict are not legal for binary
* files or properties.
@@ -4959,7 +4964,7 @@ svn_client_revprop_set(const char *propn
*
* The #svn_prop_inherited_item_t->path_or_url members of the
* #svn_prop_inherited_item_t * structures in @a *inherited_props are
- * URLs if @a target is a URL or if @target is a working copy path but the
+ * URLs if @a target is a URL or if @a target is a working copy path but the
* property represented by the structure is above the working copy root (i.e.
* the inherited property is from the cache). In all other cases the
* #svn_prop_inherited_item_t->path_or_url members are absolute working copy
Modified: subversion/branches/verify-keep-going/subversion/include/svn_dav.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/include/svn_dav.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/include/svn_dav.h (original)
+++ subversion/branches/verify-keep-going/subversion/include/svn_dav.h Wed Feb 13 10:21:33 2013
@@ -198,6 +198,13 @@ extern "C" {
* @since New in 1.8. */
#define SVN_DAV_ALLOW_BULK_UPDATES "SVN-Allow-Bulk-Updates"
+/** Assuming the request target is a Subversion repository resource,
+ * this header is returned in the OPTIONS response to indicate whether
+ * the repository supports the merge tracking feature ("yes") or not
+ * ("no").
+ * @since New in 1.8. */
+#define SVN_DAV_REPOSITORY_MERGEINFO "SVN-Repository-MergeInfo"
+
/**
* @name Fulltext MD5 headers
*
Modified: subversion/branches/verify-keep-going/subversion/include/svn_hash.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/include/svn_hash.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/include/svn_hash.h (original)
+++ subversion/branches/verify-keep-going/subversion/include/svn_hash.h Wed Feb 13 10:21:33 2013
@@ -240,6 +240,20 @@ svn_hash_from_cstring_keys(apr_hash_t **
const apr_array_header_t *keys,
apr_pool_t *pool);
+/* Shortcut for apr_hash_get() with a const char * key.
+ *
+ * @since New in 1.8.
+ */
+#define svn_hash_gets(ht, key) \
+ apr_hash_get(ht, key, APR_HASH_KEY_STRING)
+
+/* Shortcut for apr_hash_set() with a const char * key.
+ *
+ * @since New in 1.8.
+ */
+#define svn_hash_sets(ht, key, val) \
+ apr_hash_set(ht, key, APR_HASH_KEY_STRING, val)
+
/** @} */
/** @} */
Modified: subversion/branches/verify-keep-going/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/include/svn_repos.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/include/svn_repos.h (original)
+++ subversion/branches/verify-keep-going/subversion/include/svn_repos.h Wed Feb 13 10:21:33 2013
@@ -3210,7 +3210,8 @@ svn_repos_authz_read(svn_authz_t **authz
* If @a path or @a groups_path is not a valid authz rule file, then return
* #SVN_ERR_AUTHZ_INVALID_CONFIG. The contents of @a *authz_p is then
* undefined. If @a must_exist is TRUE, a missing authz or groups file
- * is also an error.
+ * is also an error other than #SVN_ERR_AUTHZ_INVALID_CONFIG (exact error
+ * depends on the access type).
*
* If @a path is a repos relative URL then @a repos_root must be set to
* the root of the repository the authz configuration will be used with.
Modified: subversion/branches/verify-keep-going/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/include/svn_wc.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/include/svn_wc.h (original)
+++ subversion/branches/verify-keep-going/subversion/include/svn_wc.h Wed Feb 13 10:21:33 2013
@@ -6794,10 +6794,20 @@ typedef enum svn_wc_merge_outcome_t
* is returned in @a *merge_content_outcome.
* ### (and what about @a *merge_props_state?)
*
+ * ### BH: Two kinds of outcome is not how it should be.
+ *
+ * ### For text, we report the outcome as 'merged' if there was some
+ * incoming change that we dealt with (even if we decided to no-op?)
+ * but the callers then convert this outcome into a notification
+ * of 'merged' only if there was already a local modification;
+ * otherwise they notify it as simply 'updated'. But for props
+ * we report a notify state of 'merged' here if there was an
+ * incoming change regardless of the local-mod state. Inconsistent.
+ *
* Use @a scratch_pool for any temporary allocation.
*
* @since New in 1.8.
- */ /* ### BH: Two kinds of outcome is not how it should be */
+ */
svn_error_t *
svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
enum svn_wc_notify_state_t *merge_props_state,
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/blame.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/blame.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/blame.c Wed Feb 13 10:21:33 2013
@@ -79,7 +79,6 @@ struct file_rev_baton {
const char *target;
svn_client_ctx_t *ctx;
const svn_diff_file_options_t *diff_options;
- svn_boolean_t ignore_mime_type;
/* name of file containing the previous revision of the file */
const char *last_filename;
struct rev *rev; /* the rev for which blame is being assigned
@@ -383,27 +382,6 @@ window_handler(svn_txdelta_window_t *win
return SVN_NO_ERROR;
}
-/* Throw an SVN_ERR_CLIENT_IS_BINARY_FILE error if PROP_DIFFS indicates a
- binary MIME type. Else, return SVN_NO_ERROR. */
-static svn_error_t *
-check_mimetype(const apr_array_header_t *prop_diffs, const char *target,
- apr_pool_t *pool)
-{
- int i;
-
- for (i = 0; i < prop_diffs->nelts; ++i)
- {
- const svn_prop_t *prop = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t);
- if (strcmp(prop->name, SVN_PROP_MIME_TYPE) == 0
- && prop->value
- && svn_mime_type_is_binary(prop->value->data))
- return svn_error_createf
- (SVN_ERR_CLIENT_IS_BINARY_FILE, 0,
- _("Cannot calculate blame information for binary file '%s'"),
- svn_dirent_local_style(target, pool));
- }
- return SVN_NO_ERROR;
-}
/* Calculate and record blame information for one revision of the file,
* by comparing the file content against the previously seen revision.
@@ -432,10 +410,6 @@ file_rev_handler(void *baton, const char
/* Clear the current pool. */
svn_pool_clear(frb->currpool);
- /* If this file has a non-textual mime-type, bail out. */
- if (! frb->ignore_mime_type)
- SVN_ERR(check_mimetype(prop_diffs, frb->target, frb->currpool));
-
if (frb->ctx->notify_func2)
{
svn_wc_notify_t *notify
@@ -640,12 +614,43 @@ svn_client_blame5(const char *target,
(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("Start revision must precede end revision"));
+ /* We check the mime-type of the yougest revision before getting all
+ the older revisions. */
+ if (!ignore_mime_type)
+ {
+ apr_hash_t *props;
+ apr_hash_index_t *hi;
+
+ SVN_ERR(svn_client_propget5(&props, NULL, SVN_PROP_MIME_TYPE,
+ target_abspath_or_url, peg_revision,
+ end, NULL, svn_depth_empty, NULL, ctx,
+ pool, pool));
+
+ /* props could be keyed on URLs or paths depending on the
+ peg_revision and end values so avoid using the key. */
+ hi = apr_hash_first(pool, props);
+ if (hi)
+ {
+ svn_string_t *value;
+
+ /* Should only be one value */
+ SVN_ERR_ASSERT(apr_hash_count(props) == 1);
+
+ value = svn__apr_hash_index_val(hi);
+ if (value && svn_mime_type_is_binary(value->data))
+ return svn_error_createf
+ (SVN_ERR_CLIENT_IS_BINARY_FILE, 0,
+ _("Cannot calculate blame information for binary file '%s'"),
+ (svn_path_is_url(target)
+ ? target : svn_dirent_local_style(target, pool)));
+ }
+ }
+
frb.start_rev = start_revnum;
frb.end_rev = end_revnum;
frb.target = target;
frb.ctx = ctx;
frb.diff_options = diff_options;
- frb.ignore_mime_type = ignore_mime_type;
frb.include_merged_revisions = include_merged_revisions;
frb.last_filename = NULL;
frb.last_original_filename = NULL;
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/cleanup.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/cleanup.c Wed Feb 13 10:21:33 2013
@@ -38,7 +38,6 @@
#include "svn_props.h"
#include "svn_private_config.h"
-#include "private/svn_wc_private.h"
/*** Code. ***/
@@ -62,308 +61,3 @@ svn_client_cleanup(const char *path,
svn_io_sleep_for_timestamps(path, scratch_pool);
return svn_error_trace(err);
}
-
-
-/* callback baton for fetch_repos_info */
-struct repos_info_baton
-{
- apr_pool_t *state_pool;
- svn_client_ctx_t *ctx;
- const char *last_repos;
- const char *last_uuid;
-};
-
-/* svn_wc_upgrade_get_repos_info_t implementation for calling
- svn_wc_upgrade() from svn_client_upgrade() */
-static svn_error_t *
-fetch_repos_info(const char **repos_root,
- const char **repos_uuid,
- void *baton,
- const char *url,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- struct repos_info_baton *ri = baton;
- apr_pool_t *subpool;
- svn_ra_session_t *ra_session;
-
- /* The same info is likely to retrieved multiple times (e.g. externals) */
- if (ri->last_repos && svn_uri__is_ancestor(ri->last_repos, url))
- {
- *repos_root = apr_pstrdup(result_pool, ri->last_repos);
- *repos_uuid = apr_pstrdup(result_pool, ri->last_uuid);
- return SVN_NO_ERROR;
- }
-
- subpool = svn_pool_create(scratch_pool);
-
- SVN_ERR(svn_client_open_ra_session(&ra_session, url, ri->ctx, subpool));
-
- SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));
- SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool));
-
- /* Store data for further calls */
- ri->last_repos = apr_pstrdup(ri->state_pool, *repos_root);
- ri->last_uuid = apr_pstrdup(ri->state_pool, *repos_uuid);
-
- svn_pool_destroy(subpool);
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_client_upgrade(const char *path,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
-{
- const char *local_abspath;
- apr_hash_t *externals;
- apr_hash_index_t *hi;
- apr_pool_t *iterpool;
- apr_pool_t *iterpool2;
- svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
- struct repos_info_baton info_baton;
-
- info_baton.state_pool = scratch_pool;
- info_baton.ctx = ctx;
- info_baton.last_repos = NULL;
- info_baton.last_uuid = NULL;
-
- if (svn_path_is_url(path))
- return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
- _("'%s' is not a local path"), path);
-
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
- SVN_ERR(svn_wc_upgrade(ctx->wc_ctx, local_abspath,
- fetch_repos_info, &info_baton,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2,
- scratch_pool));
-
- /* Now it's time to upgrade the externals too. We do it after the wc
- upgrade to avoid that errors in the externals causes the wc upgrade to
- fail. Thanks to caching the performance penalty of walking the wc a
- second time shouldn't be too severe */
- SVN_ERR(svn_client_propget5(&externals, NULL, SVN_PROP_EXTERNALS,
- local_abspath, &rev, &rev, NULL,
- svn_depth_infinity, NULL, ctx,
- scratch_pool, scratch_pool));
-
- iterpool = svn_pool_create(scratch_pool);
- iterpool2 = svn_pool_create(scratch_pool);
-
- for (hi = apr_hash_first(scratch_pool, externals); hi;
- hi = apr_hash_next(hi))
- {
- int i;
- const char *externals_parent_abspath;
- const char *externals_parent_url;
- const char *externals_parent_repos_root_url;
- const char *externals_parent = svn__apr_hash_index_key(hi);
- svn_string_t *external_desc = svn__apr_hash_index_val(hi);
- apr_array_header_t *externals_p;
- svn_error_t *err;
-
- svn_pool_clear(iterpool);
- externals_p = apr_array_make(iterpool, 1,
- sizeof(svn_wc_external_item2_t*));
-
- /* In this loop, an error causes the respective externals definition, or
- * the external (inner loop), to be skipped, so that upgrade carries on
- * with the other externals. */
-
- err = svn_dirent_get_absolute(&externals_parent_abspath,
- externals_parent, iterpool);
-
- if (!err)
- err = svn_wc__node_get_url(&externals_parent_url, ctx->wc_ctx,
- externals_parent_abspath,
- iterpool, iterpool);
- if (!err)
- err = svn_wc__node_get_repos_info(&externals_parent_repos_root_url,
- NULL,
- ctx->wc_ctx,
- externals_parent_abspath,
- iterpool, iterpool);
- if (!err)
- err = svn_wc_parse_externals_description3(
- &externals_p, svn_dirent_dirname(path, iterpool),
- external_desc->data, FALSE, iterpool);
- if (err)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(externals_parent,
- svn_wc_notify_failed_external,
- scratch_pool);
- notify->err = err;
-
- ctx->notify_func2(ctx->notify_baton2,
- notify, scratch_pool);
-
- svn_error_clear(err);
-
- /* Next externals definition, please... */
- continue;
- }
-
- for (i = 0; i < externals_p->nelts; i++)
- {
- svn_wc_external_item2_t *item;
- const char *resolved_url;
- const char *external_abspath;
- const char *repos_relpath;
- const char *repos_root_url;
- const char *repos_uuid;
- svn_node_kind_t external_kind;
- svn_revnum_t peg_revision;
- svn_revnum_t revision;
-
- item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
-
- svn_pool_clear(iterpool2);
- external_abspath = svn_dirent_join(externals_parent_abspath,
- item->target_dir,
- iterpool2);
-
- err = svn_wc__resolve_relative_external_url(
- &resolved_url,
- item,
- externals_parent_repos_root_url,
- externals_parent_url,
- scratch_pool, scratch_pool);
- if (err)
- goto handle_error;
-
- /* This is a hack. We only need to call svn_wc_upgrade() on external
- * dirs, as file externals are upgraded along with their defining
- * WC. Reading the kind will throw an exception on an external dir,
- * saying that the wc must be upgraded. If it's a file, the lookup
- * is done in an adm_dir belonging to the defining wc (which has
- * already been upgraded) and no error is returned. If it doesn't
- * exist (external that isn't checked out yet), we'll just get
- * svn_node_none. */
- err = svn_wc_read_kind(&external_kind, ctx->wc_ctx,
- external_abspath, FALSE, iterpool2);
- if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
- {
- svn_error_clear(err);
-
- err = svn_client_upgrade(external_abspath, ctx, iterpool2);
- if (err)
- goto handle_error;
- }
- else if (err)
- goto handle_error;
-
- /* The upgrade of any dir should be done now, get the now reliable
- * kind. */
- err = svn_wc_read_kind(&external_kind, ctx->wc_ctx, external_abspath,
- FALSE, iterpool2);
- if (err)
- goto handle_error;
-
- /* Update the EXTERNALS table according to the root URL,
- * relpath and uuid known in the upgraded external WC. */
-
- /* We should probably have a function that provides all three
- * of root URL, repos relpath and uuid at once, but here goes... */
-
- /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
- * when the node is not present in the file system.
- * svn_wc__node_get_repos_info() would try to derive the URL. */
- err = svn_wc__node_get_repos_relpath(&repos_relpath,
- ctx->wc_ctx,
- external_abspath,
- iterpool2, iterpool2);
- if (! err)
- {
- /* We got a repos relpath from a WC. So also get the root. */
- err = svn_wc__node_get_repos_info(&repos_root_url,
- &repos_uuid,
- ctx->wc_ctx,
- external_abspath,
- iterpool2, iterpool2);
- if (err)
- goto handle_error;
- }
- else if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- /* The external is not currently checked out. Try to figure out
- * the URL parts via the defined URL and fetch_repos_info(). */
- svn_error_clear(err);
- repos_relpath = NULL;
- repos_root_url = NULL;
- repos_uuid = NULL;
- }
- else if (err)
- goto handle_error;
-
- /* If we haven't got any information from the checked out external,
- * or if the URL information mismatches the external's definition,
- * ask fetch_repos_info() to find out the repos root. */
- if (! repos_relpath || ! repos_root_url
- || 0 != strcmp(resolved_url,
- svn_path_url_add_component2(repos_root_url,
- repos_relpath,
- scratch_pool)))
- {
- err = fetch_repos_info(&repos_root_url,
- &repos_uuid,
- &info_baton,
- resolved_url,
- scratch_pool, scratch_pool);
- if (err)
- goto handle_error;
-
- repos_relpath = svn_uri_skip_ancestor(repos_root_url,
- resolved_url,
- iterpool2);
-
- /* There's just the URL, no idea what kind the external is.
- * That's fine, as the external isn't even checked out yet.
- * The kind will be set during the next 'update'. */
- external_kind = svn_node_unknown;
- }
-
- if (err)
- goto handle_error;
-
- peg_revision = (item->peg_revision.kind == svn_opt_revision_number
- ? item->peg_revision.value.number
- : SVN_INVALID_REVNUM);
-
- revision = (item->revision.kind == svn_opt_revision_number
- ? item->revision.value.number
- : SVN_INVALID_REVNUM);
-
- err = svn_wc__upgrade_add_external_info(ctx->wc_ctx,
- external_abspath,
- external_kind,
- externals_parent,
- repos_relpath,
- repos_root_url,
- repos_uuid,
- peg_revision,
- revision,
- iterpool2);
-handle_error:
- if (err)
- {
- svn_wc_notify_t *notify =
- svn_wc_create_notify(external_abspath,
- svn_wc_notify_failed_external,
- scratch_pool);
- notify->err = err;
- ctx->notify_func2(ctx->notify_baton2,
- notify, scratch_pool);
- svn_error_clear(err);
- /* Next external node, please... */
- }
- }
- }
-
- svn_pool_destroy(iterpool);
- svn_pool_destroy(iterpool2);
-
- return SVN_NO_ERROR;
-}
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/client.h?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/client.h (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/client.h Wed Feb 13 10:21:33 2013
@@ -37,6 +37,7 @@
#include "private/svn_magic.h"
#include "private/svn_client_private.h"
+#include "private/svn_diff_tree.h"
#ifdef __cplusplus
extern "C" {
@@ -709,40 +710,27 @@ svn_client__get_inheritable_props(apr_ha
is being driven. REVISION is the revision number of the 'old' side of
the diff.
- For each deleted directory, if WALK_DELETED_DIRS is true then just call
- the 'dir_deleted' callback once, otherwise call the 'file_deleted' or
- 'dir_deleted' callback for each individual node in that subtree.
-
If TEXT_DELTAS is FALSE, then do not expect text deltas from the edit
drive, nor send the 'before' and 'after' texts to the diff callbacks;
instead, send empty files to the diff callbacks if there was a change.
This must be FALSE if the edit producer is not sending text deltas,
otherwise the file content checksum comparisons will fail.
- If NOTIFY_FUNC is non-null, invoke it with NOTIFY_BATON for each
- file and directory operated on during the edit.
-
- If ABSENT_RELPATHS is non-null, collect const char * keys in it with
- the relative paths marked as absent by the diff driver.
+ EDITOR/EDIT_BATON return the newly created editor and baton.
- EDITOR/EDIT_BATON return the newly created editor and baton. */
+ @since New in 1.8.
+ */
svn_error_t *
-svn_client__get_diff_editor(const svn_delta_editor_t **editor,
- void **edit_baton,
- svn_depth_t depth,
- svn_ra_session_t *ra_session,
- svn_revnum_t revision,
- svn_boolean_t walk_deleted_dirs,
- svn_boolean_t text_deltas,
- apr_hash_t *absent_relpaths,
- const svn_wc_diff_callbacks4_t *diff_callbacks,
- void *diff_cmd_baton,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_wc_notify_func2_t notify_func,
- void *notify_baton,
- apr_pool_t *result_pool);
-
+svn_client__get_diff_editor2(const svn_delta_editor_t **editor,
+ void **edit_baton,
+ svn_ra_session_t *ra_session,
+ svn_depth_t depth,
+ svn_revnum_t revision,
+ svn_boolean_t text_deltas,
+ const svn_diff_tree_processor_t *processor,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool);
/* ---------------------------------------------------------------- */
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/commit_util.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/commit_util.c Wed Feb 13 10:21:33 2013
@@ -765,7 +765,7 @@ harvest_status_callback(void *status_bat
svn_revnum_t dir_rev;
if (!copy_mode_root && !status->switched)
- SVN_ERR(svn_wc__node_get_base(&dir_rev, NULL, NULL, NULL, wc_ctx,
+ SVN_ERR(svn_wc__node_get_base(&dir_rev, NULL, NULL, NULL, NULL, wc_ctx,
svn_dirent_dirname(local_abspath,
scratch_pool),
scratch_pool, scratch_pool));
@@ -1239,7 +1239,8 @@ harvest_copy_committables(void *baton, v
/* Read the entry for this SRC. */
SVN_ERR_ASSERT(svn_dirent_is_absolute(pair->src_abspath_or_url));
- SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url, NULL, btn->ctx->wc_ctx,
+ SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL, &repos_root_url, NULL,
+ btn->ctx->wc_ctx,
pair->src_abspath_or_url,
pool, pool));
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/delete.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/delete.c Wed Feb 13 10:21:33 2013
@@ -79,7 +79,14 @@ find_undeletables(void *baton,
return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
_("'%s' is not under version control"),
svn_dirent_local_style(local_abspath, pool));
-
+ else if ((status->node_status == svn_wc_status_added
+ || status->node_status == svn_wc_status_replaced)
+ && status->text_status == svn_wc_status_normal
+ && (status->prop_status == svn_wc_status_normal
+ || status->prop_status == svn_wc_status_none))
+ {
+ /* Unmodified copy. Go ahead, remove it */
+ }
else if (status->node_status != svn_wc_status_normal
&& status->node_status != svn_wc_status_deleted
&& status->node_status != svn_wc_status_missing)
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/deprecated.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/deprecated.c Wed Feb 13 10:21:33 2013
@@ -2785,7 +2785,8 @@ svn_client_uuid_from_path2(const char **
apr_pool_t *scratch_pool)
{
return svn_error_trace(
- svn_wc__node_get_repos_info(NULL, uuid, ctx->wc_ctx, local_abspath,
+ svn_client_get_repos_root(NULL, uuid,
+ local_abspath, ctx,
result_pool, scratch_pool));
}
Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/diff.c?rev=1445542&r1=1445541&r2=1445542&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/diff.c Wed Feb 13 10:21:33 2013
@@ -50,6 +50,7 @@
#include "private/svn_wc_private.h"
#include "private/svn_diff_private.h"
+#include "private/svn_subr_private.h"
#include "svn_private_config.h"
@@ -92,9 +93,9 @@ make_repos_relpath(const char **repos_re
scratch_pool),
scratch_pool));
- err = svn_wc__node_get_repos_relpath(repos_relpath, wc_ctx,
- local_abspath,
- result_pool, scratch_pool);
+ err = svn_wc__node_get_repos_info(NULL, repos_relpath, NULL, NULL,
+ wc_ctx, local_abspath,
+ result_pool, scratch_pool);
if (!ra_session
|| ! err
@@ -594,6 +595,12 @@ struct diff_cmd_baton {
/* Whether deletion of a file is summarized versus showing a full diff. */
svn_boolean_t no_diff_deleted;
+ /* Whether to ignore copyfrom information when showing adds */
+ svn_boolean_t no_copyfrom_on_add;
+
+ /* Empty files for creating diffs or NULL if not used yet */
+ const char *empty_file;
+
svn_wc_context_t *wc_ctx;
/* The RA session used during diffs involving the repository. */
@@ -996,6 +1003,30 @@ diff_file_added(svn_wc_notify_state_t *c
rev2 = diff_cmd_baton->revnum2;
}
+ if (diff_cmd_baton->no_copyfrom_on_add
+ && (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_revision)))
+ {
+ apr_hash_t *empty_hash = apr_hash_make(scratch_pool);
+ apr_array_header_t *new_changes;
+
+ /* Rebase changes on having no left source. */
+ if (!diff_cmd_baton->empty_file)
+ SVN_ERR(svn_io_open_unique_file3(NULL, &diff_cmd_baton->empty_file,
+ NULL, svn_io_file_del_on_pool_cleanup,
+ diff_cmd_baton->pool, scratch_pool));
+
+ SVN_ERR(svn_prop_diffs(&new_changes,
+ svn_prop__patch(original_props, prop_changes,
+ scratch_pool),
+ empty_hash,
+ scratch_pool));
+
+ tmpfile1 = diff_cmd_baton->empty_file;
+ prop_changes = new_changes;
+ original_props = empty_hash;
+ copyfrom_revision = SVN_INVALID_REVNUM;
+ }
+
if (diff_cmd_baton->no_diff_added)
{
const char *index_path = diff_relpath;
@@ -1192,37 +1223,6 @@ static const svn_wc_diff_callbacks4_t di
the user specifies two dates that resolve to the same revision. */
-
-
-/* Helper function: given a working-copy ABSPATH_OR_URL, return its
- associated url in *URL, allocated in RESULT_POOL. If ABSPATH_OR_URL is
- *already* a URL, that's fine, return ABSPATH_OR_URL allocated in
- RESULT_POOL.
-
- Use SCRATCH_POOL for temporary allocations. */
-static svn_error_t *
-convert_to_url(const char **url,
- svn_wc_context_t *wc_ctx,
- const char *abspath_or_url,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- if (svn_path_is_url(abspath_or_url))
- {
- *url = apr_pstrdup(result_pool, abspath_or_url);
- return SVN_NO_ERROR;
- }
-
- SVN_ERR(svn_wc__node_get_url(url, wc_ctx, abspath_or_url,
- result_pool, scratch_pool));
- if (! *url)
- return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
- _("Path '%s' has no URL"),
- svn_dirent_local_style(abspath_or_url,
- scratch_pool));
- return SVN_NO_ERROR;
-}
-
/** Check if paths PATH_OR_URL1 and PATH_OR_URL2 are urls and if the
* revisions REVISION1 and REVISION2 are local. If PEG_REVISION is not
* unspecified, ensure that at least one of the two revisions is not
@@ -1384,24 +1384,25 @@ diff_prepare_repos_repos(const char **ur
{
const char *abspath_or_url2;
const char *abspath_or_url1;
+ const char *repos_root_url;
if (!svn_path_is_url(path_or_url2))
- SVN_ERR(svn_dirent_get_absolute(&abspath_or_url2, path_or_url2,
- pool));
+ {
+ SVN_ERR(svn_dirent_get_absolute(&abspath_or_url2, path_or_url2, pool));
+ SVN_ERR(svn_wc__node_get_url(url2, ctx->wc_ctx, abspath_or_url2,
+ pool, pool));
+ }
else
- abspath_or_url2 = path_or_url2;
+ *url2 = abspath_or_url2 = apr_pstrdup(pool, path_or_url2);
if (!svn_path_is_url(path_or_url1))
- SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1,
- pool));
+ {
+ SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1, pool));
+ SVN_ERR(svn_wc__node_get_url(url1, ctx->wc_ctx, abspath_or_url1,
+ pool, pool));
+ }
else
- abspath_or_url1 = path_or_url1;
-
- /* Figure out URL1 and URL2. */
- SVN_ERR(convert_to_url(url1, ctx->wc_ctx, abspath_or_url1,
- pool, pool));
- SVN_ERR(convert_to_url(url2, ctx->wc_ctx, abspath_or_url2,
- pool, pool));
+ *url1 = abspath_or_url1 = apr_pstrdup(pool, path_or_url1);
/* We need exactly one BASE_PATH, so we'll let the BASE_PATH
calculated for PATH_OR_URL2 override the one for PATH_OR_URL1
@@ -1488,18 +1489,23 @@ diff_prepare_repos_repos(const char **ur
else if (*kind2 == svn_node_none)
SVN_ERR(check_diff_target_exists(*url2, *rev1, *rev2, *ra_session, pool));
+ SVN_ERR(svn_ra_get_repos_root2(*ra_session, &repos_root_url, pool));
+
/* Choose useful anchors and targets for our two URLs. */
*anchor1 = *url1;
*anchor2 = *url2;
*target1 = "";
*target2 = "";
- /* If one of the targets is a file, use the parent directory as anchor. */
- if (*kind1 == svn_node_file || *kind2 == svn_node_file)
+ /* If none of the targets is the repository root open the parent directory
+ to allow describing replacement of the target itself */
+ if (strcmp(*url1, repos_root_url) != 0
+ && strcmp(*url2, repos_root_url) != 0)
{
svn_uri_split(anchor1, target1, *url1, pool);
svn_uri_split(anchor2, target2, *url2, pool);
- if (*base_path)
+ if (*base_path
+ && (*kind1 == svn_node_file || *kind2 == svn_node_file))
*base_path = svn_dirent_dirname(*base_path, pool);
SVN_ERR(svn_ra_reparent(*ra_session, *anchor1, pool));
}
@@ -1630,300 +1636,6 @@ diff_wc_wc(const char *path1,
return SVN_NO_ERROR;
}
-/* Create an array of regular properties in PROP_HASH, filtering entry-props
- * and wc-props. Allocate the returned array in RESULT_POOL.
- * Use SCRATCH_POOL for temporary allocations. */
-static apr_array_header_t *
-make_regular_props_array(apr_hash_t *prop_hash,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *regular_props;
- apr_hash_index_t *hi;
-
- regular_props = apr_array_make(result_pool, 0, sizeof(svn_prop_t));
- for (hi = apr_hash_first(scratch_pool, prop_hash); hi;
- hi = apr_hash_next(hi))
- {
- const char *name = svn__apr_hash_index_key(hi);
- svn_string_t *value = svn__apr_hash_index_val(hi);
- svn_prop_kind_t prop_kind = svn_property_kind2(name);
-
- if (prop_kind == svn_prop_regular_kind)
- {
- svn_prop_t *prop = apr_palloc(scratch_pool, sizeof(svn_prop_t));
-
- prop->name = name;
- prop->value = value;
- APR_ARRAY_PUSH(regular_props, svn_prop_t) = *prop;
- }
- }
-
- return regular_props;
-}
-
-/* Create a hash of regular properties from PROP_HASH, filtering entry-props
- * and wc-props. Allocate the returned hash in RESULT_POOL.
- * Use SCRATCH_POOL for temporary allocations. */
-static apr_hash_t *
-make_regular_props_hash(apr_hash_t *prop_hash,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- apr_hash_t *regular_props;
- apr_hash_index_t *hi;
-
- regular_props = apr_hash_make(result_pool);
- for (hi = apr_hash_first(scratch_pool, prop_hash); hi;
- hi = apr_hash_next(hi))
- {
- const char *name = svn__apr_hash_index_key(hi);
- svn_string_t *value = svn__apr_hash_index_val(hi);
- svn_prop_kind_t prop_kind = svn_property_kind2(name);
-
- if (prop_kind == svn_prop_regular_kind)
- apr_hash_set(regular_props, name, APR_HASH_KEY_STRING, value);
- }
-
- return regular_props;
-}
-
-/* Handle an added or deleted diff target file for a repos<->repos diff.
- *
- * Using the provided diff CALLBACKS and the CALLBACK_BATON, show the file
- * TARGET@PEG_REVISION as added or deleted, depending on SHOW_DELETION.
- * TARGET is a path relative to RA_SESSION's URL.
- * REV1 and REV2 are the revisions being compared.
- * Use SCRATCH_POOL for temporary allocations. */
-static svn_error_t *
-diff_repos_repos_added_or_deleted_file(const char *target,
- svn_revnum_t peg_revision,
- svn_revnum_t rev1,
- svn_revnum_t rev2,
- svn_boolean_t show_deletion,
- const char *empty_file,
- const svn_wc_diff_callbacks4_t
- *callbacks,
- struct diff_cmd_baton *callback_baton,
- svn_ra_session_t *ra_session,
- apr_pool_t *scratch_pool)
-{
- const char *file_abspath;
- svn_stream_t *content;
- apr_hash_t *prop_hash;
-
- SVN_ERR(svn_stream_open_unique(&content, &file_abspath, NULL,
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_ra_get_file(ra_session, target, peg_revision, content, NULL,
- &prop_hash, scratch_pool));
- SVN_ERR(svn_stream_close(content));
-
- if (show_deletion)
- {
- SVN_ERR(callbacks->file_deleted(NULL, NULL,
- target, file_abspath, empty_file,
- apr_hash_get(prop_hash,
- SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- NULL,
- make_regular_props_hash(
- prop_hash, scratch_pool, scratch_pool),
- callback_baton, scratch_pool));
- }
- else
- {
- SVN_ERR(callbacks->file_added(NULL, NULL, NULL,
- target, empty_file, file_abspath,
- rev1, rev2, NULL,
- apr_hash_get(prop_hash, SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- NULL, SVN_INVALID_REVNUM,
- make_regular_props_array(prop_hash,
- scratch_pool,
- scratch_pool),
- NULL, callback_baton, scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Handle an added or deleted diff target directory for a repos<->repos diff.
- *
- * Using the provided diff CALLBACKS and the CALLBACK_BATON, show the
- * directory TARGET@PEG_REVISION, and all of its children, as added or deleted,
- * depending on SHOW_DELETION. TARGET is a path relative to RA_SESSION's URL.
- * REV1 and REV2 are the revisions being compared.
- * Use SCRATCH_POOL for temporary allocations. */
-static svn_error_t *
-diff_repos_repos_added_or_deleted_dir(const char *target,
- svn_revnum_t revision,
- svn_revnum_t rev1,
- svn_revnum_t rev2,
- svn_boolean_t show_deletion,
- const char *empty_file,
- const svn_wc_diff_callbacks4_t
- *callbacks,
- struct diff_cmd_baton *callback_baton,
- svn_ra_session_t *ra_session,
- apr_pool_t *scratch_pool)
-{
- apr_hash_t *dirents;
- apr_hash_t *props;
- apr_pool_t *iterpool;
- apr_hash_index_t *hi;
-
- SVN_ERR(svn_ra_get_dir2(ra_session, &dirents, NULL, &props,
- target, revision, SVN_DIRENT_KIND,
- scratch_pool));
-
- if (show_deletion)
- SVN_ERR(callbacks->dir_deleted(NULL, NULL, target, callback_baton,
- scratch_pool));
- else
- SVN_ERR(callbacks->dir_added(NULL, NULL, NULL, NULL,
- target, revision,
- NULL, SVN_INVALID_REVNUM,
- callback_baton, scratch_pool));
- if (props)
- {
- if (show_deletion)
- SVN_ERR(callbacks->dir_props_changed(NULL, NULL, target, FALSE,
- apr_array_make(scratch_pool, 0,
- sizeof(svn_prop_t)),
- make_regular_props_hash(
- props, scratch_pool,
- scratch_pool),
- callback_baton, scratch_pool));
- else
- SVN_ERR(callbacks->dir_props_changed(NULL, NULL, target, TRUE,
- make_regular_props_array(
- props, scratch_pool,
- scratch_pool),
- NULL,
- callback_baton, scratch_pool));
- }
-
- iterpool = svn_pool_create(scratch_pool);
- for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
- {
- const char *name = svn__apr_hash_index_key(hi);
- svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
- const char *child_target;
-
- svn_pool_clear(iterpool);
-
- child_target = svn_relpath_join(target, name, iterpool);
-
- if (dirent->kind == svn_node_dir)
- SVN_ERR(diff_repos_repos_added_or_deleted_dir(child_target,
- revision, rev1, rev2,
- show_deletion,
- empty_file,
- callbacks,
- callback_baton,
- ra_session,
- iterpool));
- else if (dirent->kind == svn_node_file)
- SVN_ERR(diff_repos_repos_added_or_deleted_file(child_target,
- revision, rev1, rev2,
- show_deletion,
- empty_file,
- callbacks,
- callback_baton,
- ra_session,
- iterpool));
- }
- svn_pool_destroy(iterpool);
-
- if (!show_deletion)
- SVN_ERR(callbacks->dir_closed(NULL, NULL, NULL, target, TRUE,
- callback_baton, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-
-/* Handle an added or deleted diff target for a repos<->repos diff.
- *
- * Using the provided diff CALLBACKS and the CALLBACK_BATON, show
- * TARGET@PEG_REVISION, and all of its children, if any, as added or deleted.
- * TARGET is a path relative to RA_SESSION's URL.
- * REV1 and REV2 are the revisions being compared.
- * Use SCRATCH_POOL for temporary allocations. */
-static svn_error_t *
-diff_repos_repos_added_or_deleted_target(const char *target1,
- const char *target2,
- svn_revnum_t rev1,
- svn_revnum_t rev2,
- svn_node_kind_t kind1,
- svn_node_kind_t kind2,
- const svn_wc_diff_callbacks4_t
- *callbacks,
- struct diff_cmd_baton *callback_baton,
- svn_ra_session_t *ra_session,
- apr_pool_t *scratch_pool)
-{
- const char *existing_target;
- svn_revnum_t existing_rev;
- svn_node_kind_t existing_kind;
- svn_boolean_t show_deletion;
- const char *empty_file;
-
- SVN_ERR_ASSERT(kind1 == svn_node_none || kind2 == svn_node_none);
-
- /* Are we showing an addition or deletion? */
- show_deletion = (kind2 == svn_node_none);
-
- /* Which target is being added/deleted? Is it a file or a directory? */
- if (show_deletion)
- {
- existing_target = target1;
- existing_rev = rev1;
- existing_kind = kind1;
- }
- else
- {
- existing_target = target2;
- existing_rev = rev2;
- existing_kind = kind2;
- }
-
- /* All file content will be diffed against the empty file. */
- SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file, NULL,
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
-
- if (existing_kind == svn_node_file)
- {
- /* Get file content and show a diff against the empty file. */
- SVN_ERR(diff_repos_repos_added_or_deleted_file(existing_target,
- existing_rev,
- rev1, rev2,
- show_deletion,
- empty_file,
- callbacks,
- callback_baton,
- ra_session,
- scratch_pool));
- }
- else
- {
- /* Walk the added/deleted tree and show a diff for each child. */
- SVN_ERR(diff_repos_repos_added_or_deleted_dir(existing_target,
- existing_rev,
- rev1, rev2,
- show_deletion,
- empty_file,
- callbacks,
- callback_baton,
- ra_session,
- scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
/* Perform a diff between two repository paths.
PATH_OR_URL1 and PATH_OR_URL2 may be either URLs or the working copy paths.
@@ -1954,6 +1666,8 @@ diff_repos_repos(const svn_wc_diff_callb
const svn_delta_editor_t *diff_editor;
void *diff_edit_baton;
+ const svn_diff_tree_processor_t *diff_processor;
+
const char *url1;
const char *url2;
const char *base_path;
@@ -1975,6 +1689,14 @@ diff_repos_repos(const svn_wc_diff_callb
revision1, revision2, peg_revision,
pool));
+ /* Set up the repos_diff editor on BASE_PATH, if available.
+ Otherwise, we just use "". */
+
+ SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
+ callbacks, callback_baton,
+ TRUE /* walk_deleted_dirs */,
+ pool, pool));
+
/* Get actual URLs. */
callback_baton->orig_path_1 = url1;
callback_baton->orig_path_2 = url2;
@@ -1986,21 +1708,41 @@ diff_repos_repos(const svn_wc_diff_callb
callback_baton->ra_session = ra_session;
callback_baton->anchor = base_path;
- if (kind1 == svn_node_none || kind2 == svn_node_none)
+ /* The repository can bring in a new working copy, but not delete
+ everything. Luckily our new diff handler can just be reversed. */
+ if (kind2 == svn_node_none)
{
- /* One side of the diff does not exist.
- * Walk the tree that does exist, showing a series of additions
- * or deletions. */
- SVN_ERR(diff_repos_repos_added_or_deleted_target(target1, target2,
- rev1, rev2,
- kind1, kind2,
- callbacks,
- callback_baton,
- ra_session,
- pool));
- return SVN_NO_ERROR;
+ const char *str_tmp;
+ svn_revnum_t rev_tmp;
+
+ str_tmp = url2;
+ url2 = url1;
+ url1 = str_tmp;
+
+ rev_tmp = rev2;
+ rev2 = rev1;
+ rev1 = rev_tmp;
+
+ str_tmp = anchor2;
+ anchor2 = anchor1;
+ anchor1 = str_tmp;
+
+ str_tmp = target2;
+ target2 = target1;
+ target1 = str_tmp;
+
+ diff_processor = svn_diff__tree_processor_reverse_create(diff_processor,
+ NULL, pool);
}
+ /* Filter the first path component using a filter processor, until we fixed
+ the diff processing to handle this directly */
+ if ((kind1 != svn_node_file && kind2 != svn_node_file) && target1[0] != '\0')
+ {
+ diff_processor = svn_diff__tree_processor_filter_create(diff_processor,
+ target1, pool);
+ }
+
/* Now, we open an extra RA session to the correct anchor
location for URL1. This is used during the editor calls to fetch file
contents. */
@@ -2008,189 +1750,28 @@ diff_repos_repos(const svn_wc_diff_callb
anchor1, NULL, NULL, FALSE,
TRUE, ctx, pool));
- /* Set up the repos_diff editor on BASE_PATH, if available.
- Otherwise, we just use "". */
- SVN_ERR(svn_client__get_diff_editor(
+ SVN_ERR(svn_client__get_diff_editor2(
&diff_editor, &diff_edit_baton,
- depth,
- extra_ra_session, rev1, TRUE /* walk_deleted_dirs */,
+ extra_ra_session, depth,
+ rev1,
TRUE /* text_deltas */,
- NULL /* absent relpaths */,
- callbacks, callback_baton,
+ diff_processor,
ctx->cancel_func, ctx->cancel_baton,
- NULL /* no notify_func */, NULL /* no notify_baton */,
pool));
/* We want to switch our txn into URL2 */
- SVN_ERR(svn_ra_do_diff3
- (ra_session, &reporter, &reporter_baton, rev2, target1,
- depth, ignore_ancestry, TRUE /* text_deltas */,
- url2, diff_editor, diff_edit_baton, pool));
+ SVN_ERR(svn_ra_do_diff3(ra_session, &reporter, &reporter_baton,
+ rev2, target1,
+ depth, ignore_ancestry, TRUE /* text_deltas */,
+ url2, diff_editor, diff_edit_baton, pool));
/* Drive the reporter; do the diff. */
SVN_ERR(reporter->set_path(reporter_baton, "", rev1,
svn_depth_infinity,
FALSE, NULL,
pool));
- return reporter->finish_report(reporter_baton, pool);
-}
-
-
-/* Using CALLBACKS, show a REPOS->WC diff for a file TARGET, which in the
- * working copy is at FILE2_ABSPATH. KIND1 is the node kind of the repository
- * target (either svn_node_file or svn_node_none). REV is the revision the
- * working file is diffed against. RA_SESSION points at the URL of the file
- * in the repository and is used to get the file's repository-version content,
- * if necessary. The other parameters are as in diff_repos_wc(). */
-static svn_error_t *
-diff_repos_wc_file_target(const char *target,
- const char *file2_abspath,
- svn_node_kind_t kind1,
- svn_revnum_t rev,
- svn_boolean_t reverse,
- svn_boolean_t show_copies_as_adds,
- const svn_wc_diff_callbacks4_t *callbacks,
- void *callback_baton,
- svn_ra_session_t *ra_session,
- svn_client_ctx_t *ctx,
- apr_pool_t *scratch_pool)
-{
- const char *file1_abspath;
- svn_stream_t *file1_content;
- svn_stream_t *file2_content;
- apr_hash_t *file1_props = NULL;
- apr_hash_t *file2_props;
- svn_boolean_t is_copy = FALSE;
- apr_hash_t *keywords = NULL;
- svn_string_t *keywords_prop;
- svn_subst_eol_style_t eol_style;
- const char *eol_str;
-
- /* Get content and props of file 1 (the remote file). */
- SVN_ERR(svn_stream_open_unique(&file1_content, &file1_abspath, NULL,
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
- if (kind1 == svn_node_file)
- {
- if (show_copies_as_adds)
- SVN_ERR(svn_wc__node_get_origin(&is_copy,
- NULL, NULL, NULL, NULL, NULL,
- ctx->wc_ctx, file2_abspath,
- FALSE, scratch_pool, scratch_pool));
- /* If showing copies as adds, diff against the empty file. */
- if (!(show_copies_as_adds && is_copy))
- SVN_ERR(svn_ra_get_file(ra_session, "", rev, file1_content,
- NULL, &file1_props, scratch_pool));
- }
-
- SVN_ERR(svn_stream_close(file1_content));
-
- SVN_ERR(svn_wc_prop_list2(&file2_props, ctx->wc_ctx, file2_abspath,
- scratch_pool, scratch_pool));
-
- /* We might have to create a normalised version of the working file. */
- svn_subst_eol_style_from_value(&eol_style, &eol_str,
- apr_hash_get(file2_props,
- SVN_PROP_EOL_STYLE,
- APR_HASH_KEY_STRING));
- keywords_prop = apr_hash_get(file2_props, SVN_PROP_KEYWORDS,
- APR_HASH_KEY_STRING);
- if (keywords_prop)
- SVN_ERR(svn_subst_build_keywords2(&keywords, keywords_prop->data,
- NULL, NULL, 0, NULL,
- scratch_pool));
- if (svn_subst_translation_required(eol_style, SVN_SUBST_NATIVE_EOL_STR,
- keywords, FALSE, TRUE))
- {
- svn_stream_t *working_content;
- svn_stream_t *normalized_content;
-
- SVN_ERR(svn_stream_open_readonly(&working_content, file2_abspath,
- scratch_pool, scratch_pool));
-
- /* Create a temporary file and copy normalised data into it. */
- SVN_ERR(svn_stream_open_unique(&file2_content, &file2_abspath, NULL,
- svn_io_file_del_on_pool_cleanup,
- scratch_pool, scratch_pool));
- normalized_content = svn_subst_stream_translated(
- file2_content, SVN_SUBST_NATIVE_EOL_STR,
- TRUE, keywords, FALSE, scratch_pool);
- SVN_ERR(svn_stream_copy3(working_content, normalized_content,
- ctx->cancel_func, ctx->cancel_baton,
- scratch_pool));
- }
- if (kind1 == svn_node_file && !(show_copies_as_adds && is_copy))
- {
- SVN_ERR(callbacks->file_opened(NULL, NULL, target,
- reverse ? SVN_INVALID_REVNUM : rev,
- callback_baton, scratch_pool));
-
- if (reverse)
- SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, target,
- file2_abspath, file1_abspath,
- SVN_INVALID_REVNUM, rev,
- apr_hash_get(file2_props,
- SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- apr_hash_get(file1_props,
- SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- make_regular_props_array(
- file1_props, scratch_pool,
- scratch_pool),
- file2_props,
- callback_baton, scratch_pool));
- else
- SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, target,
- file1_abspath, file2_abspath,
- rev, SVN_INVALID_REVNUM,
- apr_hash_get(file1_props,
- SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- apr_hash_get(file2_props,
- SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- make_regular_props_array(
- file2_props, scratch_pool,
- scratch_pool),
- file1_props,
- callback_baton, scratch_pool));
- }
- else
- {
- if (reverse)
- {
- SVN_ERR(callbacks->file_deleted(NULL, NULL,
- target, file2_abspath, file1_abspath,
- apr_hash_get(file2_props,
- SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- NULL,
- make_regular_props_hash(
- file2_props, scratch_pool,
- scratch_pool),
- callback_baton, scratch_pool));
- }
- else
- {
- SVN_ERR(callbacks->file_added(NULL, NULL, NULL, target,
- file1_abspath, file2_abspath,
- rev, SVN_INVALID_REVNUM,
- NULL,
- apr_hash_get(file2_props,
- SVN_PROP_MIME_TYPE,
- APR_HASH_KEY_STRING),
- NULL, SVN_INVALID_REVNUM,
- make_regular_props_array(
- file2_props, scratch_pool,
- scratch_pool),
- NULL,
- callback_baton, scratch_pool));
- }
- }
-
- return SVN_NO_ERROR;
+ return svn_error_trace(reporter->finish_report(reporter_baton, pool));
}
/* Perform a diff between a repository path and a working-copy path.
@@ -2219,8 +1800,9 @@ diff_repos_wc(const char *path_or_url1,
void *callback_baton,
struct diff_cmd_baton *cmd_baton,
svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
+ apr_pool_t *pool = scratch_pool;
const char *url1, *anchor, *anchor_url, *target;
svn_revnum_t rev;
svn_ra_session_t *ra_session;
@@ -2237,22 +1819,27 @@ diff_repos_wc(const char *path_or_url1,
svn_node_kind_t kind1;
svn_node_kind_t kind2;
svn_boolean_t is_copy;
- svn_revnum_t copyfrom_rev;
- const char *copy_source_repos_relpath;
- const char *copy_source_repos_root_url;
+ svn_revnum_t cf_revision;
+ const char *cf_repos_relpath;
+ const char *cf_repos_root_url;
SVN_ERR_ASSERT(! svn_path_is_url(path2));
if (!svn_path_is_url(path_or_url1))
- SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1, pool));
+ {
+ SVN_ERR(svn_dirent_get_absolute(&abspath_or_url1, path_or_url1, pool));
+ SVN_ERR(svn_wc__node_get_url(&url1, ctx->wc_ctx, abspath_or_url1,
+ pool, pool));
+ }
else
- abspath_or_url1 = path_or_url1;
+ {
+ url1 = path_or_url1;
+ abspath_or_url1 = path_or_url1;
+ }
SVN_ERR(svn_dirent_get_absolute(&abspath2, path2, pool));
/* Convert path_or_url1 to a URL to feed to do_diff. */
- SVN_ERR(convert_to_url(&url1, ctx->wc_ctx, abspath_or_url1, pool, pool));
-
SVN_ERR(svn_wc_get_actual_target2(&anchor, &target,
ctx->wc_ctx, path2,
pool, pool));
@@ -2261,10 +1848,7 @@ diff_repos_wc(const char *path_or_url1,
SVN_ERR(svn_dirent_get_absolute(&anchor_abspath, anchor, pool));
SVN_ERR(svn_wc__node_get_url(&anchor_url, ctx->wc_ctx, anchor_abspath,
pool, pool));
- if (! anchor_url)
- return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
- _("Directory '%s' has no URL"),
- svn_dirent_local_style(anchor, pool));
+ SVN_ERR_ASSERT(anchor_url != NULL);
/* If we are performing a pegged diff, we need to find out what our
actual URLs will be. */
@@ -2313,32 +1897,14 @@ diff_repos_wc(const char *path_or_url1,
cmd_baton->revnum2 = rev;
/* Check if our diff target is a copied node. */
- SVN_ERR(svn_wc__node_get_origin(&is_copy,
- ©from_rev,
- ©_source_repos_relpath,
- ©_source_repos_root_url,
+ SVN_ERR(svn_wc__node_get_origin(&is_copy,
+ &cf_revision,
+ &cf_repos_relpath,
+ &cf_repos_root_url,
NULL, NULL,
ctx->wc_ctx, abspath2,
FALSE, pool, pool));
- /* If both diff targets can be diffed as files, fetch the appropriate
- * file content from the repository and generate a diff against the
- * local version of the file.
- * However, if comparing the repository version of the file to the BASE
- * tree version we can use the diff editor to transmit a delta instead
- * of potentially huge file content. */
- if ((!rev2_is_base || is_copy) &&
- (kind1 == svn_node_file || kind1 == svn_node_none)
- && kind2 == svn_node_file)
- {
- SVN_ERR(diff_repos_wc_file_target(target, abspath2, kind1, rev,
- reverse, show_copies_as_adds,
- callbacks, callback_baton,
- ra_session, ctx, pool));
-
- return SVN_NO_ERROR;
- }
-
/* Use the diff editor to generate the diff. */
SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
SVN_RA_CAPABILITY_DEPTH, pool));
@@ -2347,7 +1913,7 @@ diff_repos_wc(const char *path_or_url1,
anchor_abspath,
target,
depth,
- ignore_ancestry,
+ ignore_ancestry || is_copy,
show_copies_as_adds,
use_git_diff_format,
rev2_is_base,
@@ -2366,30 +1932,40 @@ diff_repos_wc(const char *path_or_url1,
if (is_copy)
{
- const char *copyfrom_url;
const char *copyfrom_parent_url;
const char *copyfrom_basename;
svn_depth_t copy_depth;
cmd_baton->repos_wc_diff_target_is_copy = TRUE;
- /* We're diffing a locally copied/moved directory.
+ /* We're diffing a locally copied/moved node.
* Describe the copy source to the reporter instead of the copy itself.
* Doing the latter would generate a single add_directory() call to the
* diff editor which results in an unexpected diff (the copy would
* be shown as deleted). */
- copyfrom_url = apr_pstrcat(pool, copy_source_repos_root_url, "/",
- copy_source_repos_relpath, (char *)NULL);
- svn_uri_split(©from_parent_url, ©from_basename,
- copyfrom_url, pool);
+ if (cf_repos_relpath[0] == '\0')
+ {
+ copyfrom_parent_url = cf_repos_root_url;
+ copyfrom_basename = "";
+ }
+ else
+ {
+ const char *parent_relpath;
+ svn_relpath_split(&parent_relpath, ©from_basename,
+ cf_repos_relpath, scratch_pool);
+
+ copyfrom_parent_url = svn_path_url_add_component2(cf_repos_root_url,
+ parent_relpath,
+ scratch_pool);
+ }
SVN_ERR(svn_ra_reparent(ra_session, copyfrom_parent_url, pool));
/* Tell the RA layer we want a delta to change our txn to URL1 */
SVN_ERR(svn_ra_do_diff3(ra_session,
&reporter, &reporter_baton,
rev,
- copyfrom_basename,
+ target,
diff_depth,
ignore_ancestry,
TRUE, /* text_deltas */
@@ -2399,9 +1975,23 @@ diff_repos_wc(const char *path_or_url1,
/* Report the copy source. */
SVN_ERR(svn_wc__node_get_depth(©_depth, ctx->wc_ctx, abspath2,
pool));
- SVN_ERR(reporter->set_path(reporter_baton, "", copyfrom_rev,
- copy_depth, FALSE, NULL, pool));
-
+
+ if (copy_depth == svn_depth_unknown)
+ copy_depth = svn_depth_infinity;
+
+ SVN_ERR(reporter->set_path(reporter_baton, "",
+ cf_revision,
+ copy_depth, FALSE, NULL, scratch_pool));
+
+ if (strcmp(target, copyfrom_basename) != 0)
+ SVN_ERR(reporter->link_path(reporter_baton, target,
+ svn_path_url_add_component2(
+ cf_repos_root_url,
+ cf_repos_relpath,
+ scratch_pool),
+ cf_revision,
+ copy_depth, FALSE, NULL, scratch_pool));
+
/* Finish the report to generate the diff. */
SVN_ERR(reporter->finish_report(reporter_baton, pool));
}
@@ -2502,6 +2092,7 @@ do_diff(const svn_wc_diff_callbacks4_t *
SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, pool));
SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
+ depth,
callbacks,
callback_baton,
ctx, pool));
@@ -2646,6 +2237,8 @@ diff_summarize_repos_repos(svn_client_di
const svn_delta_editor_t *diff_editor;
void *diff_edit_baton;
+ const svn_diff_tree_processor_t *diff_processor;
+
const char *url1;
const char *url2;
const char *base_path;
@@ -2669,43 +2262,58 @@ diff_summarize_repos_repos(svn_client_di
revision1, revision2,
peg_revision, pool));
- if (kind1 == svn_node_none || kind2 == svn_node_none)
- {
- /* One side of the diff does not exist.
- * Walk the tree that does exist, showing a series of additions
- * or deletions. */
- SVN_ERR(svn_client__get_diff_summarize_callbacks(
- &callbacks, &callback_baton, target1, FALSE,
- summarize_func, summarize_baton, pool));
- SVN_ERR(diff_repos_repos_added_or_deleted_target(target1, target2,
- rev1, rev2,
- kind1, kind2,
- callbacks,
- callback_baton,
- ra_session,
- pool));
- return SVN_NO_ERROR;
- }
-
+ /* Set up the repos_diff editor. */
SVN_ERR(svn_client__get_diff_summarize_callbacks(
&callbacks, &callback_baton,
target1, FALSE, summarize_func, summarize_baton, pool));
+ SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
+ callbacks, callback_baton,
+ TRUE /* walk_deleted_dirs */,
+ pool, pool));
+
+
+ /* The repository can bring in a new working copy, but not delete
+ everything. Luckily our new diff handler can just be reversed. */
+ if (kind2 == svn_node_none)
+ {
+ const char *str_tmp;
+ svn_revnum_t rev_tmp;
+
+ str_tmp = url2;
+ url2 = url1;
+ url1 = str_tmp;
+
+ rev_tmp = rev2;
+ rev2 = rev1;
+ rev1 = rev_tmp;
+
+ str_tmp = anchor2;
+ anchor2 = anchor1;
+ anchor1 = str_tmp;
+
+ str_tmp = target2;
+ target2 = target1;
+ target1 = str_tmp;
+
+ diff_processor = svn_diff__tree_processor_reverse_create(diff_processor,
+ NULL, pool);
+ }
+
/* Now, we open an extra RA session to the correct anchor
location for URL1. This is used to get the kind of deleted paths. */
SVN_ERR(svn_client__open_ra_session_internal(&extra_ra_session, NULL,
anchor1, NULL, NULL, FALSE,
TRUE, ctx, pool));
- /* Set up the repos_diff editor. */
- SVN_ERR(svn_client__get_diff_editor(&diff_editor, &diff_edit_baton,
- depth,
- extra_ra_session, rev1, TRUE /* walk_deleted_dirs */,
- FALSE /* text_deltas */,
- NULL /* absent relpaths */,
- callbacks, callback_baton,
- ctx->cancel_func, ctx->cancel_baton,
- NULL /* notify_func */, NULL /* notify_baton */, pool));
+ SVN_ERR(svn_client__get_diff_editor2(&diff_editor, &diff_edit_baton,
+ extra_ra_session,
+ depth,
+ rev1,
+ FALSE /* text_deltas */,
+ diff_processor,
+ ctx->cancel_func, ctx->cancel_baton,
+ pool));
/* We want to switch our txn into URL2 */
SVN_ERR(svn_ra_do_diff3
@@ -2718,7 +2326,7 @@ diff_summarize_repos_repos(svn_client_di
SVN_ERR(reporter->set_path(reporter_baton, "", rev1,
svn_depth_infinity,
FALSE, NULL, pool));
- return reporter->finish_report(reporter_baton, pool);
+ return svn_error_trace(reporter->finish_report(reporter_baton, pool));
}
/* This is basically just the guts of svn_client_diff_summarize[_peg]2(). */
@@ -2799,6 +2407,7 @@ do_diff_summarize(svn_client_diff_summar
summarize_func, summarize_baton, pool));
SVN_ERR(svn_client__arbitrary_nodes_diff(abspath1, abspath2,
+ depth,
callbacks,
callback_baton,
ctx, pool));
@@ -2971,6 +2580,8 @@ svn_client_diff6(const apr_array_header_
diff_cmd_baton.use_git_diff_format = use_git_diff_format;
diff_cmd_baton.no_diff_added = no_diff_added;
diff_cmd_baton.no_diff_deleted = no_diff_deleted;
+ diff_cmd_baton.no_copyfrom_on_add = show_copies_as_adds;
+
diff_cmd_baton.wc_ctx = ctx->wc_ctx;
diff_cmd_baton.ra_session = NULL;
diff_cmd_baton.anchor = NULL;
@@ -3032,6 +2643,8 @@ svn_client_diff_peg6(const apr_array_hea
diff_cmd_baton.use_git_diff_format = use_git_diff_format;
diff_cmd_baton.no_diff_added = no_diff_added;
diff_cmd_baton.no_diff_deleted = no_diff_deleted;
+ diff_cmd_baton.no_copyfrom_on_add = show_copies_as_adds;
+
diff_cmd_baton.wc_ctx = ctx->wc_ctx;
diff_cmd_baton.ra_session = NULL;
diff_cmd_baton.anchor = NULL;