You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/16 16:57:42 UTC
svn commit: r1339210 [1/3] - in /subversion/branches/ev2-export: ./
build/generator/templates/ contrib/server-side/ subversion/include/
subversion/libsvn_client/ subversion/libsvn_ra/ subversion/libsvn_ra_serf/
subversion/libsvn_repos/ subversion/libsv...
Author: hwright
Date: Wed May 16 14:57:41 2012
New Revision: 1339210
URL: http://svn.apache.org/viewvc?rev=1339210&view=rev
Log:
On the ev2-export branch:
Bring up-to-date with trunk.
(Hey, at least it's been 2 days since the last merge.)
Removed:
subversion/branches/ev2-export/contrib/server-side/svn-fast-backup
Modified:
subversion/branches/ev2-export/ (props changed)
subversion/branches/ev2-export/CHANGES
subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt
subversion/branches/ev2-export/subversion/include/svn_types.h
subversion/branches/ev2-export/subversion/libsvn_client/blame.c
subversion/branches/ev2-export/subversion/libsvn_client/cat.c
subversion/branches/ev2-export/subversion/libsvn_client/client.h
subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c
subversion/branches/ev2-export/subversion/libsvn_client/diff.c
subversion/branches/ev2-export/subversion/libsvn_client/export.c
subversion/branches/ev2-export/subversion/libsvn_client/list.c
subversion/branches/ev2-export/subversion/libsvn_client/log.c
subversion/branches/ev2-export/subversion/libsvn_client/merge.c
subversion/branches/ev2-export/subversion/libsvn_client/mergeinfo.c
subversion/branches/ev2-export/subversion/libsvn_client/prop_commands.c
subversion/branches/ev2-export/subversion/libsvn_client/ra.c
subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c
subversion/branches/ev2-export/subversion/libsvn_ra_serf/log.c
subversion/branches/ev2-export/subversion/libsvn_repos/replay.c
subversion/branches/ev2-export/subversion/libsvn_subr/io.c
subversion/branches/ev2-export/subversion/libsvn_subr/skel.c
subversion/branches/ev2-export/subversion/libsvn_subr/stream.c
subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
subversion/branches/ev2-export/subversion/svnsync/sync.c
subversion/branches/ev2-export/subversion/tests/cmdline/authz_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/diff_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/import_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/log_tests.py
Propchange: subversion/branches/ev2-export/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1338208-1339207
Modified: subversion/branches/ev2-export/CHANGES
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/CHANGES?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/CHANGES (original)
+++ subversion/branches/ev2-export/CHANGES Wed May 16 14:57:41 2012
@@ -19,6 +19,7 @@ http://svn.apache.org/repos/asf/subversi
* new SVNUseUTF8 configuration option for mod_dav_svn (issue #2487)
* new SVNHooksEnv configuration option for mod_dav_svn (r1239966)
* new --ignore-properties option for 'svn diff' (r1239553. -617)
+ * new --properties-only option for 'svn diff' (r1336110)
* new --patch-compatible option for 'svn diff' (r1239561)
* new SvnPubSub distributed commit hooks (tools/server-side/svnpubsub)
* 'svn diff' can compare arbitrary files and directories (r1310291, et al)
Modified: subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt (original)
+++ subversion/branches/ev2-export/build/generator/templates/vcnet_vcxproj.ezt Wed May 16 14:57:41 2012
@@ -33,7 +33,8 @@
[for platforms][for configs] <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='[configs.name]|[platforms]'" Label="Configuration">
<ConfigurationType>[config_type]</ConfigurationType>
<UseDebugLibraries>[is configs.name "Debug"]true[else]false[end]</UseDebugLibraries>
- <PlatformToolset>[toolset_version]</PlatformToolset>
+[is configs.name "Release"] <WholeProgramOptimization>true</WholeProgramOptimization>
+[end] <PlatformToolset>[toolset_version]</PlatformToolset>
</PropertyGroup>
[end][end] <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
Modified: subversion/branches/ev2-export/subversion/include/svn_types.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_types.h?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_types.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_types.h Wed May 16 14:57:41 2012
@@ -910,6 +910,10 @@ typedef struct svn_log_entry_t
* Whether @a revision should be interpreted as non-inheritable in the
* same sense of #svn_merge_range_t.
*
+ * Only set when this #svn_log_entry_t instance is returned by the
+ * libsvn_client mergeinfo apis. Currently always FALSE when the
+ * #svn_log_entry_t instance is reported by the ra layer.
+ *
* @since New in 1.7.
*/
svn_boolean_t non_inheritable;
Modified: subversion/branches/ev2-export/subversion/libsvn_client/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/blame.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/blame.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/blame.c Wed May 16 14:57:41 2012
@@ -593,6 +593,7 @@ svn_client_blame5(const char *target,
struct file_rev_baton frb;
svn_ra_session_t *ra_session;
svn_revnum_t start_revnum, end_revnum;
+ svn_client__pathrev_t *end_loc;
struct blame *walk, *walk_merged = NULL;
apr_pool_t *iterpool;
svn_stream_t *last_stream;
@@ -610,9 +611,10 @@ svn_client_blame5(const char *target,
SVN_ERR(svn_dirent_get_absolute(&target_abspath_or_url, target, pool));
/* Get an RA plugin for this filesystem object. */
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &end_revnum, NULL,
- target, NULL, peg_revision, end,
- ctx, pool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &end_loc,
+ target, NULL, peg_revision, end,
+ ctx, pool));
+ end_revnum = end_loc->rev;
SVN_ERR(svn_client__get_revision_number(&start_revnum, NULL, ctx->wc_ctx,
target_abspath_or_url, ra_session,
Modified: subversion/branches/ev2-export/subversion/libsvn_client/cat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/cat.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/cat.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/cat.c Wed May 16 14:57:41 2012
@@ -183,11 +183,10 @@ svn_client_cat2(svn_stream_t *out,
apr_pool_t *pool)
{
svn_ra_session_t *ra_session;
- svn_revnum_t rev;
+ svn_client__pathrev_t *loc;
svn_string_t *eol_style;
svn_string_t *keywords;
apr_hash_t *props;
- const char *url;
svn_stream_t *output = out;
svn_error_t *err;
@@ -227,20 +226,21 @@ svn_client_cat2(svn_stream_t *out,
}
/* Get an RA plugin for this filesystem object. */
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev,
- &url, path_or_url, NULL,
- peg_revision,
- revision, ctx, pool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+ path_or_url, NULL,
+ peg_revision,
+ revision, ctx, pool));
/* Grab some properties we need to know in order to figure out if anything
special needs to be done with this file. */
- err = svn_ra_get_file(ra_session, "", rev, NULL, NULL, &props, pool);
+ err = svn_ra_get_file(ra_session, "", loc->rev, NULL, NULL, &props, pool);
if (err)
{
if (err->apr_err == SVN_ERR_FS_NOT_FILE)
{
return svn_error_createf(SVN_ERR_CLIENT_IS_DIRECTORY, err,
- _("URL '%s' refers to a directory"), url);
+ _("URL '%s' refers to a directory"),
+ loc->url);
}
else
{
@@ -284,7 +284,7 @@ svn_client_cat2(svn_stream_t *out,
SVN_ERR(svn_subst_build_keywords2
(&kw, keywords->data,
cmt_rev->data,
- url,
+ loc->url,
when,
cmt_author ? cmt_author->data : NULL,
pool));
@@ -297,7 +297,7 @@ svn_client_cat2(svn_stream_t *out,
eol_str, FALSE, kw, TRUE, pool);
}
- SVN_ERR(svn_ra_get_file(ra_session, "", rev, output, NULL, NULL, pool));
+ SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, output, NULL, NULL, pool));
if (out != output)
/* Close the interjected stream */
Modified: subversion/branches/ev2-export/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/client.h?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/client.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/client.h Wed May 16 14:57:41 2012
@@ -227,29 +227,15 @@ svn_client__get_youngest_common_ancestor
for a URL or 'working' for a WC path. If REVISION->kind is
'unspecified', the operative revision is the peg revision.
- Store the resulting ra_session in *RA_SESSION_P. Store the actual
- revision number of the object in *REV_P, and the final resulting
- URL in *URL_P. REV_P and/or URL_P may be NULL if not wanted.
+ Store the resulting ra_session in *RA_SESSION_P. Store the final
+ resolved location of the object in *RESOLVED_LOC_P. RESOLVED_LOC_P
+ may be NULL if not wanted.
Use authentication baton cached in CTX to authenticate against the
repository.
Use POOL for all allocations. */
svn_error_t *
-svn_client__ra_session_from_path(svn_ra_session_t **ra_session_p,
- svn_revnum_t *rev_p,
- const char **url_p,
- const char *path_or_url,
- const char *base_dir_abspath,
- const svn_opt_revision_t *peg_revision,
- const svn_opt_revision_t *revision,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool);
-
-/* Like svn_client__ra_session_from_path() but returning a path-rev
- * instead of separate URL and rev outputs. RESOLVED_LOC_P may be NULL
- * if not wanted. */
-svn_error_t *
svn_client__ra_session_from_path2(svn_ra_session_t **ra_session_p,
svn_client__pathrev_t **resolved_loc_p,
const char *path_or_url,
Modified: subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/commit_util.c Wed May 16 14:57:41 2012
@@ -194,7 +194,11 @@ fixup_commit_error(const char *local_abs
/* Add a new commit candidate (described by all parameters except
`COMMITTABLES') to the COMMITTABLES hash. All of the commit item's
- members are allocated out of RESULT_POOL. */
+ members are allocated out of RESULT_POOL.
+
+ If the state flag specifies that a lock must be used, store the token in LOCK
+ in lock_tokens.
+ */
static svn_error_t *
add_committable(svn_client__committables_t *committables,
const char *local_abspath,
@@ -205,6 +209,8 @@ add_committable(svn_client__committables
const char *copyfrom_relpath,
svn_revnum_t copyfrom_rev,
apr_byte_t state_flags,
+ apr_hash_t *lock_tokens,
+ const svn_lock_t *lock,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -260,6 +266,16 @@ add_committable(svn_client__committables
APR_HASH_KEY_STRING,
new_item);
+ if (lock
+ && lock_tokens
+ && (state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN))
+ {
+ apr_hash_set(lock_tokens,
+ new_item->url,
+ APR_HASH_KEY_STRING,
+ apr_pstrdup(result_pool, lock->token));
+ }
+
return SVN_NO_ERROR;
}
@@ -414,6 +430,8 @@ harvest_committables(const char *local_a
{
struct harvest_baton baton;
+ SVN_ERR_ASSERT((just_locked && lock_tokens) || !just_locked);
+
baton.root_abspath = local_abspath;
baton.committables = committables;
baton.lock_tokens = lock_tokens;
@@ -529,6 +547,7 @@ harvest_not_present_for_copy(svn_wc_cont
NULL /* copyfrom_relpath */,
SVN_INVALID_REVNUM /* copyfrom_rev */,
SVN_CLIENT_COMMIT_ITEM_DELETE,
+ NULL, NULL,
result_pool, scratch_pool));
}
@@ -561,13 +580,11 @@ harvest_status_callback(void *status_bat
svn_boolean_t is_harvest_root =
(strcmp(baton->root_abspath, local_abspath) == 0);
svn_client__committables_t *committables = baton->committables;
- apr_hash_t *lock_tokens = baton->lock_tokens;
const char *repos_root_url = status->repos_root_url;
const char *commit_relpath = NULL;
svn_boolean_t copy_mode_root = (baton->commit_relpath && is_harvest_root);
svn_boolean_t just_locked = baton->just_locked;
apr_hash_t *changelists = baton->changelists;
- apr_hash_t *danglers = baton->danglers;
svn_wc_notify_func2_t notify_func = baton->notify_func;
void *notify_baton = baton->notify_baton;
svn_wc_context_t *wc_ctx = baton->wc_ctx;
@@ -631,7 +648,6 @@ harvest_status_callback(void *status_bat
SVN_ERR_ASSERT((copy_mode && commit_relpath)
|| (! copy_mode && ! commit_relpath));
SVN_ERR_ASSERT((copy_mode_root && copy_mode) || ! copy_mode_root);
- SVN_ERR_ASSERT((just_locked && lock_tokens) || !just_locked);
/* Save the result for reuse. */
matches_changelists = ((changelists == NULL)
@@ -829,52 +845,43 @@ harvest_status_callback(void *status_bat
/* If the entry has a lock token and it is already a commit candidate,
or the caller wants unmodified locked items to be treated as
such, note this fact. */
- if (status->lock && lock_tokens && (state_flags || just_locked))
+ if (status->lock && baton->lock_tokens && (state_flags || just_locked))
{
state_flags |= SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN;
}
/* Now, if this is something to commit, add it to our list. */
- if (state_flags)
+ if (matches_changelists
+ && state_flags)
{
- if (matches_changelists)
- {
- /* Finally, add the committable item. */
- SVN_ERR(add_committable(committables, local_abspath,
- status->kind,
- repos_root_url,
- copy_mode
+ /* Finally, add the committable item. */
+ SVN_ERR(add_committable(committables, local_abspath,
+ status->kind,
+ repos_root_url,
+ copy_mode
? commit_relpath
: status->repos_relpath,
- copy_mode
+ copy_mode
? SVN_INVALID_REVNUM
: node_rev,
- cf_relpath,
- cf_rev,
- state_flags,
- result_pool, scratch_pool));
- if (state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)
- apr_hash_set(lock_tokens,
- svn_path_url_add_component2(
- repos_root_url, status->repos_relpath,
- result_pool),
- APR_HASH_KEY_STRING,
- apr_pstrdup(result_pool,
- status->lock->token));
- }
+ cf_relpath,
+ cf_rev,
+ state_flags,
+ baton->lock_tokens, status->lock,
+ result_pool, scratch_pool));
}
/* Fetch lock tokens for descendants of deleted nodes. */
- if (lock_tokens
- && (state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE))
+ if (matches_changelists
+ && (state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+ && baton->lock_tokens)
{
apr_hash_t *local_relpath_tokens;
apr_hash_index_t *hi;
- apr_pool_t *token_pool = apr_hash_pool_get(lock_tokens);
SVN_ERR(svn_wc__node_get_lock_tokens_recursive(
&local_relpath_tokens, wc_ctx, local_abspath,
- token_pool, scratch_pool));
+ result_pool, scratch_pool));
/* Add tokens to existing hash. */
for (hi = apr_hash_first(scratch_pool, local_relpath_tokens);
@@ -887,22 +894,35 @@ harvest_status_callback(void *status_bat
apr_hash_this(hi, &key, &klen, &val);
- apr_hash_set(lock_tokens, key, klen, val);
+ apr_hash_set(baton->lock_tokens, key, klen, val);
}
}
- /* Make sure we check for dangling children on additions */
- if (state_flags && is_added && is_harvest_root && danglers)
+ /* Make sure we check for dangling children on additions
+
+ We perform this operation on the harvest root, and on roots caused by
+ changelist filtering.
+ */
+ if (matches_changelists
+ && (is_harvest_root || baton->changelists)
+ && state_flags
+ && is_added
+ && baton->danglers)
{
- /* If a node is added, it's parent must exist in the repository at the
+ /* If a node is added, its parent must exist in the repository at the
time of committing */
-
+ apr_hash_t *danglers = baton->danglers;
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));
+ /* First check if parent is already in the list of commits
+ (Common case for GUI clients that provide a list of commit targets) */
+ if (look_up_committable(committables, parent_abspath, scratch_pool))
+ parent_added = FALSE; /* Skip all expensive checks */
+ else
+ SVN_ERR(svn_wc__node_is_added(&parent_added, wc_ctx, parent_abspath,
+ scratch_pool));
if (parent_added)
{
@@ -930,8 +950,7 @@ harvest_status_callback(void *status_bat
}
}
- if ((state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
- && !(state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
+ if (is_deleted && !is_added)
{
/* Skip all descendants */
if (status->kind == svn_node_dir)
Modified: subversion/branches/ev2-export/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/diff.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/diff.c Wed May 16 14:57:41 2012
@@ -1528,7 +1528,8 @@ resolve_pegged_diff_target_url(const cha
ctx, scratch_pool);
if (err)
{
- if (err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES)
+ if (err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES ||
+ err->apr_err == SVN_ERR_FS_NOT_FOUND)
{
svn_error_clear(err);
*resolved_url = NULL;
@@ -1545,6 +1546,8 @@ resolve_pegged_diff_target_url(const cha
* Return URLs and peg revisions in *URL1, *REV1 and in *URL2, *REV2.
* Return suitable anchors in *ANCHOR1 and *ANCHOR2, and targets in
* *TARGET1 and *TARGET2, based on *URL1 and *URL2.
+ * Indicate the corresponding node kinds in *KIND1 and *KIND2, and verify
+ * that at least one of the diff targets exists.
* Set *BASE_PATH corresponding to the URL opened in the new *RA_SESSION
* which is pointing at *ANCHOR1.
* Use client context CTX. Do all allocations in POOL. */
@@ -1558,6 +1561,8 @@ diff_prepare_repos_repos(const char **ur
const char **anchor2,
const char **target1,
const char **target2,
+ svn_node_kind_t *kind1,
+ svn_node_kind_t *kind2,
svn_ra_session_t **ra_session,
svn_client_ctx_t *ctx,
const char *path_or_url1,
@@ -1567,7 +1572,6 @@ diff_prepare_repos_repos(const char **ur
const svn_opt_revision_t *peg_revision,
apr_pool_t *pool)
{
- svn_node_kind_t kind1, kind2;
const char *abspath_or_url2;
const char *abspath_or_url1;
@@ -1644,18 +1648,18 @@ diff_prepare_repos_repos(const char **ur
SVN_ERR(svn_client__get_revision_number(rev2, NULL, ctx->wc_ctx,
(path_or_url2 == *url2) ? NULL : abspath_or_url2,
*ra_session, revision2, pool));
- SVN_ERR(svn_ra_check_path(*ra_session, "", *rev2, &kind2, pool));
+ SVN_ERR(svn_ra_check_path(*ra_session, "", *rev2, kind2, pool));
/* Do the same for the first target. */
SVN_ERR(svn_ra_reparent(*ra_session, *url1, pool));
SVN_ERR(svn_client__get_revision_number(rev1, NULL, ctx->wc_ctx,
(strcmp(path_or_url1, *url1) == 0) ? NULL : abspath_or_url1,
*ra_session, revision1, pool));
- SVN_ERR(svn_ra_check_path(*ra_session, "", *rev1, &kind1, pool));
+ SVN_ERR(svn_ra_check_path(*ra_session, "", *rev1, kind1, pool));
/* Either both URLs must exist at their respective revisions,
* or one of them may be missing from one side of the diff. */
- if (kind1 == svn_node_none && kind2 == svn_node_none)
+ if (*kind1 == svn_node_none && *kind2 == svn_node_none)
{
if (strcmp(*url1, *url2) == 0)
return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
@@ -1669,9 +1673,9 @@ diff_prepare_repos_repos(const char **ur
"'%ld'"),
*url1, *url2, *rev1, *rev2);
}
- else if (kind1 == svn_node_none)
+ else if (*kind1 == svn_node_none)
SVN_ERR(check_diff_target_exists(*url1, *rev2, *rev1, *ra_session, pool));
- else if (kind2 == svn_node_none)
+ else if (*kind2 == svn_node_none)
SVN_ERR(check_diff_target_exists(*url2, *rev1, *rev2, *ra_session, pool));
/* Choose useful anchors and targets for our two URLs. */
@@ -1679,57 +1683,9 @@ diff_prepare_repos_repos(const char **ur
*anchor2 = *url2;
*target1 = "";
*target2 = "";
- if ((kind1 == svn_node_none) || (kind2 == svn_node_none))
- {
- svn_node_kind_t kind;
- const char *repos_root;
- const char *new_anchor;
- svn_revnum_t rev;
-
- /* The diff target does not exist on one side of the diff.
- * This can happen if the target was added or deleted within the
- * revision range being diffed.
- * However, we don't know how deep within a added/deleted subtree the
- * diff target is. Find a common parent that exists on both sides of
- * the diff and use it as anchor for the diff operation.
- *
- * ### This can fail due to authz restrictions (like in issue #3242).
- * ### But it is the only option we have right now to try to get
- * ### a usable diff in this situation. */
-
- SVN_ERR(svn_ra_get_repos_root2(*ra_session, &repos_root, pool));
-
- /* Since we already know that one of the URLs does exist,
- * look for an existing parent of the URL which doesn't exist. */
- new_anchor = (kind1 == svn_node_none ? *anchor1 : *anchor2);
- rev = (kind1 == svn_node_none ? *rev1 : *rev2);
- do
- {
- if (strcmp(new_anchor, repos_root) != 0)
- {
- new_anchor = svn_path_uri_decode(svn_uri_dirname(new_anchor,
- pool),
- pool);
- if (*base_path)
- *base_path = svn_dirent_dirname(*base_path, pool);
- }
-
- SVN_ERR(svn_ra_reparent(*ra_session, new_anchor, pool));
- SVN_ERR(svn_ra_check_path(*ra_session, "", rev, &kind, pool));
- }
- while (kind != svn_node_dir);
- *anchor1 = *anchor2 = new_anchor;
- /* Diff targets must be relative to the new anchor. */
- *target1 = svn_uri_skip_ancestor(new_anchor, *url1, pool);
- *target2 = svn_uri_skip_ancestor(new_anchor, *url2, pool);
- SVN_ERR_ASSERT(*target1 && *target2);
- if (kind1 == svn_node_none)
- kind1 = svn_node_dir;
- else
- kind2 = svn_node_dir;
- }
- else if ((kind1 == svn_node_file) || (kind2 == svn_node_file))
+ /* If one of the targets is a file, use the parent directory as anchor. */
+ if (*kind1 == svn_node_file || *kind2 == svn_node_file)
{
svn_uri_split(anchor1, target1, *url1, pool);
svn_uri_split(anchor2, target2, *url2, pool);
@@ -2334,6 +2290,299 @@ 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.
@@ -2370,6 +2619,8 @@ diff_repos_repos(const svn_wc_diff_callb
const char *base_path;
svn_revnum_t rev1;
svn_revnum_t rev2;
+ svn_node_kind_t kind1;
+ svn_node_kind_t kind2;
const char *anchor1;
const char *anchor2;
const char *target1;
@@ -2379,7 +2630,8 @@ diff_repos_repos(const svn_wc_diff_callb
/* Prepare info for the repos repos diff. */
SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
&anchor1, &anchor2, &target1, &target2,
- &ra_session, ctx, path_or_url1, path_or_url2,
+ &kind1, &kind2, &ra_session,
+ ctx, path_or_url1, path_or_url2,
revision1, revision2, peg_revision,
pool));
@@ -2394,6 +2646,21 @@ 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)
+ {
+ /* 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;
+ }
+
/* 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. */
@@ -2741,6 +3008,8 @@ diff_summarize_repos_repos(svn_client_di
const char *base_path;
svn_revnum_t rev1;
svn_revnum_t rev2;
+ svn_node_kind_t kind1;
+ svn_node_kind_t kind2;
const char *anchor1;
const char *anchor2;
const char *target1;
@@ -2752,10 +3021,29 @@ diff_summarize_repos_repos(svn_client_di
/* Prepare info for the repos repos diff. */
SVN_ERR(diff_prepare_repos_repos(&url1, &url2, &base_path, &rev1, &rev2,
&anchor1, &anchor2, &target1, &target2,
- &ra_session, ctx,
- path_or_url1, path_or_url2, revision1, revision2,
+ &kind1, &kind2, &ra_session,
+ ctx, path_or_url1, path_or_url2,
+ 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,
+ 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;
+ }
+
SVN_ERR(svn_client__get_diff_summarize_callbacks(
&callbacks, &callback_baton,
target1, summarize_func, summarize_baton, pool));
Modified: subversion/branches/ev2-export/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/export.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/export.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/export.c Wed May 16 14:57:41 2012
@@ -957,20 +957,19 @@ svn_client_export5(svn_revnum_t *result_
if (from_is_url || ! SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
{
- svn_revnum_t revnum;
- const char *url;
+ svn_client__pathrev_t *loc;
svn_ra_session_t *ra_session;
svn_node_kind_t kind;
struct edit_baton *eb = apr_pcalloc(pool, sizeof(*eb));
/* Get the RA connection. */
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
- &url, from_path_or_url, NULL,
- peg_revision,
- revision, ctx, pool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+ from_path_or_url, NULL,
+ peg_revision,
+ revision, ctx, pool));
eb->root_path = to_path;
- eb->root_url = url;
+ eb->root_url = loc->url;
eb->force = overwrite;
eb->target_revision = &edit_revision;
eb->externals = apr_hash_make(pool);
@@ -981,7 +980,7 @@ svn_client_export5(svn_revnum_t *result_
eb->notify_func = ctx->notify_func2;
eb->notify_baton = ctx->notify_baton2;
- SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool));
+ SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, pool));
if (kind == svn_node_file)
{
@@ -1020,7 +1019,7 @@ svn_client_export5(svn_revnum_t *result_
tmp_stream = svn_stream_buffered(pool);
- SVN_ERR(svn_ra_get_file(ra_session, "", revnum,
+ SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev,
tmp_stream, NULL, &props, pool));
/* Since you cannot actually root an editor at a file, we
@@ -1042,13 +1041,13 @@ svn_client_export5(svn_revnum_t *result_
/* Manufacture a basic 'report' to the update reporter. */
SVN_ERR(svn_ra_do_update2(ra_session,
&reporter, &report_baton,
- revnum,
+ loc->rev,
"", /* no sub-target */
depth,
FALSE, /* don't want copyfrom-args */
export_editor, edit_baton, pool));
- SVN_ERR(reporter->set_path(report_baton, "", revnum,
+ SVN_ERR(reporter->set_path(report_baton, "", loc->rev,
/* Depth is irrelevant, as we're
passing start_empty=TRUE anyway. */
svn_depth_infinity,
Modified: subversion/branches/ev2-export/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/list.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/list.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/list.c Wed May 16 14:57:41 2012
@@ -237,9 +237,8 @@ svn_client_list2(const char *path_or_url
apr_pool_t *pool)
{
svn_ra_session_t *ra_session;
- svn_revnum_t rev;
+ svn_client__pathrev_t *loc;
svn_dirent_t *dirent;
- const char *url;
const char *fs_path;
svn_error_t *err;
apr_hash_t *locks;
@@ -249,20 +248,19 @@ svn_client_list2(const char *path_or_url
dirent_fields |= SVN_DIRENT_KIND;
/* Get an RA plugin for this filesystem object. */
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev,
- &url, path_or_url, NULL,
- peg_revision,
- revision, ctx, pool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+ path_or_url, NULL,
+ peg_revision,
+ revision, ctx, pool));
- SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &fs_path, url,
- pool));
+ fs_path = svn_client__pathrev_fspath(loc, pool);
- SVN_ERR(ra_stat_compatible(ra_session, rev, &dirent, dirent_fields,
+ SVN_ERR(ra_stat_compatible(ra_session, loc->rev, &dirent, dirent_fields,
ctx, pool));
if (! dirent)
return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
_("URL '%s' non-existent in revision %ld"),
- url, rev);
+ loc->url, loc->rev);
/* Maybe get all locks under url. */
if (fetch_locks)
@@ -292,7 +290,7 @@ svn_client_list2(const char *path_or_url
&& (depth == svn_depth_files
|| depth == svn_depth_immediates
|| depth == svn_depth_infinity))
- SVN_ERR(get_dir_contents(dirent_fields, "", rev, ra_session, locks,
+ SVN_ERR(get_dir_contents(dirent_fields, "", loc->rev, ra_session, locks,
fs_path, depth, ctx, list_func, baton, pool));
return SVN_NO_ERROR;
Modified: subversion/branches/ev2-export/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/log.c?rev=1339210&r1=1339209&r2=1339210&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/log.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/log.c Wed May 16 14:57:41 2012
@@ -101,23 +101,22 @@ svn_client__get_copy_source(const char *
copyfrom_info_t copyfrom_info = { 0 };
apr_pool_t *sesspool = svn_pool_create(pool);
svn_ra_session_t *ra_session;
- svn_revnum_t at_rev;
- const char *at_url;
+ svn_client__pathrev_t *at_loc;
copyfrom_info.is_first = TRUE;
copyfrom_info.path = NULL;
copyfrom_info.rev = SVN_INVALID_REVNUM;
copyfrom_info.pool = pool;
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &at_rev, &at_url,
- path_or_url, NULL,
- revision, revision,
- ctx, sesspool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &at_loc,
+ path_or_url, NULL,
+ revision, revision,
+ ctx, sesspool));
/* Find the copy source. Walk the location segments to find the revision
at which this node was created (copied or added). */
- err = svn_ra_get_location_segments(ra_session, "", at_rev, at_rev,
+ err = svn_ra_get_location_segments(ra_session, "", at_loc->rev, at_loc->rev,
SVN_INVALID_REVNUM,
copyfrom_info_receiver, ©from_info,
pool);
@@ -281,7 +280,6 @@ svn_client_log5(const apr_array_header_t
svn_ra_session_t *ra_session;
const char *url_or_path;
svn_boolean_t has_log_revprops;
- const char *actual_url;
apr_array_header_t *condensed_targets;
svn_opt_revision_t session_opt_rev;
const char *ra_target;
@@ -474,6 +472,8 @@ svn_client_log5(const apr_array_header_t
{
+ svn_client__pathrev_t *actual_loc;
+
/* If this is a revision type that requires access to the working copy,
* we use our initial target path to figure out where to root the RA
* session, otherwise we use our URL. */
@@ -483,7 +483,7 @@ svn_client_log5(const apr_array_header_t
else
ra_target = url_or_path;
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, NULL, &actual_url,
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &actual_loc,
ra_target, NULL,
&peg_rev, &session_opt_rev,
ctx, pool));
@@ -497,7 +497,7 @@ svn_client_log5(const apr_array_header_t
/* Create ra session on first use */
rb.ra_session_pool = pool;
- rb.ra_session_url = actual_url;
+ rb.ra_session_url = actual_loc->url;
}
}