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/01/13 22:40:38 UTC
svn commit: r1231318 [10/35] - in /subversion/branches/revprop-packing: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/ contrib/server-side/mod_dontdothat/
notes/ notes/http-and-webdav/ not...
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/patch.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/patch.c Fri Jan 13 21:40:26 2012
@@ -670,7 +670,7 @@ init_prop_target(prop_patch_target_t **p
}
content->existed = (value != NULL);
new_prop_target->value = value;
- new_prop_target->patched_value = svn_stringbuf_create("", result_pool);
+ new_prop_target->patched_value = svn_stringbuf_create_empty(result_pool);
/* Wire up the read and write callbacks. */
@@ -811,13 +811,20 @@ write_file(void *baton, const char *buf,
* with the fewest path components, the shortest basename, and the shortest
* total file name length (in that order). In case of a tie, return the new
* filename. This heuristic is also used by Larry Wall's UNIX patch (except
- * that it prompts for a filename in case of a tie). */
+ * that it prompts for a filename in case of a tie).
+ * Additionally, for compatibility with git, if one of the filenames
+ * is "/dev/null", use the other filename. */
static const char *
choose_target_filename(const svn_patch_t *patch)
{
apr_size_t old;
apr_size_t new;
+ if (strcmp(patch->old_filename, "/dev/null") == 0)
+ return patch->new_filename;
+ if (strcmp(patch->new_filename, "/dev/null") == 0)
+ return patch->old_filename;
+
old = svn_path_component_count(patch->old_filename);
new = svn_path_component_count(patch->new_filename);
@@ -1692,7 +1699,7 @@ apply_hunk(patch_target_t *target, targe
&eol_str, &eof,
iterpool, iterpool));
lines_read++;
- if (! eof && lines_read > hi->fuzz &&
+ if (lines_read > hi->fuzz &&
lines_read <= svn_diff_hunk_get_modified_length(hi->hunk) - hi->fuzz)
{
apr_size_t len;
@@ -2493,8 +2500,15 @@ install_patched_prop_targets(patch_targe
target->added = TRUE;
}
- /* Attempt to set the property, and reject all hunks if this fails. */
- prop_val = svn_stringbuf__morph_into_string(prop_target->patched_value);
+ /* Attempt to set the property, and reject all hunks if this
+ fails. If the property had a non-empty value, but now has
+ an empty one, we'll just delete the property altogether. */
+ if (prop_target->value && prop_target->value->len
+ && prop_target->patched_value && !prop_target->patched_value->len)
+ prop_val = NULL;
+ else
+ prop_val = svn_stringbuf__morph_into_string(prop_target->patched_value);
+
if (dry_run)
{
const svn_string_t *canon_propval;
@@ -2716,6 +2730,7 @@ delete_empty_dirs(apr_array_header_t *ta
SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
target_info = APR_ARRAY_IDX(targets_info, i, patch_target_info_t *);
+
parent = svn_dirent_dirname(target_info->local_abspath, iterpool);
if (apr_hash_get(non_empty_dirs, parent, APR_HASH_KEY_STRING))
@@ -2818,54 +2833,36 @@ delete_empty_dirs(apr_array_header_t *ta
return SVN_NO_ERROR;
}
-/* Baton for apply_patches(). */
-typedef struct apply_patches_baton_t {
- /* The path to the patch file. */
- const char *patch_abspath;
-
- /* The abspath to the working copy the patch should be applied to. */
- const char *abs_wc_path;
-
- /* Indicates whether we're doing a dry run. */
- svn_boolean_t dry_run;
-
- /* Number of leading components to strip from patch target paths. */
- int strip_count;
-
- /* Whether to apply the patch in reverse. */
- svn_boolean_t reverse;
-
- /* Indicates whether we should ignore whitespace when matching context
- * lines */
- svn_boolean_t ignore_whitespace;
-
- /* As in svn_client_patch(). */
- svn_boolean_t remove_tempfiles;
-
- /* As in svn_client_patch(). */
- svn_client_patch_func_t patch_func;
- void *patch_baton;
-
- /* The client context. */
- svn_client_ctx_t *ctx;
-} apply_patches_baton_t;
-
-/* Callback for use with svn_wc__call_with_write_lock().
- * This function is the main entry point into the patch code. */
+/* This function is the main entry point into the patch code. */
static svn_error_t *
-apply_patches(void *baton,
- apr_pool_t *result_pool,
+apply_patches(/* The path to the patch file. */
+ const char *patch_abspath,
+ /* The abspath to the working copy the patch should be applied to. */
+ const char *abs_wc_path,
+ /* Indicates whether we're doing a dry run. */
+ svn_boolean_t dry_run,
+ /* Number of leading components to strip from patch target paths. */
+ int strip_count,
+ /* Whether to apply the patch in reverse. */
+ svn_boolean_t reverse,
+ /* Whether to ignore whitespace when matching context lines. */
+ svn_boolean_t ignore_whitespace,
+ /* As in svn_client_patch(). */
+ svn_boolean_t remove_tempfiles,
+ /* As in svn_client_patch(). */
+ svn_client_patch_func_t patch_func,
+ void *patch_baton,
+ /* The client context. */
+ svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
svn_patch_t *patch;
apr_pool_t *iterpool;
svn_patch_file_t *patch_file;
apr_array_header_t *targets_info;
- apply_patches_baton_t *btn = baton;
/* Try to open the patch file. */
- SVN_ERR(svn_diff_open_patch_file(&patch_file, btn->patch_abspath,
- scratch_pool));
+ SVN_ERR(svn_diff_open_patch_file(&patch_file, patch_abspath, scratch_pool));
/* Apply patches. */
targets_info = apr_array_make(scratch_pool, 0,
@@ -2875,23 +2872,21 @@ apply_patches(void *baton,
{
svn_pool_clear(iterpool);
- if (btn->ctx->cancel_func)
- SVN_ERR(btn->ctx->cancel_func(btn->ctx->cancel_baton));
+ if (ctx->cancel_func)
+ SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
- btn->reverse, btn->ignore_whitespace,
+ reverse, ignore_whitespace,
iterpool, iterpool));
if (patch)
{
patch_target_t *target;
- SVN_ERR(apply_one_patch(&target, patch, btn->abs_wc_path,
- btn->ctx->wc_ctx, btn->strip_count,
- btn->ignore_whitespace,
- btn->remove_tempfiles,
- btn->patch_func, btn->patch_baton,
- btn->ctx->cancel_func,
- btn->ctx->cancel_baton,
+ SVN_ERR(apply_one_patch(&target, patch, abs_wc_path,
+ ctx->wc_ctx, strip_count,
+ ignore_whitespace, remove_tempfiles,
+ patch_func, patch_baton,
+ ctx->cancel_func, ctx->cancel_baton,
iterpool, iterpool));
if (! target->filtered)
{
@@ -2901,35 +2896,32 @@ apply_patches(void *baton,
target_info->local_abspath = apr_pstrdup(scratch_pool,
target->local_abspath);
target_info->deleted = target->deleted;
- APR_ARRAY_PUSH(targets_info,
- patch_target_info_t *) = target_info;
if (! target->skipped)
{
+ APR_ARRAY_PUSH(targets_info,
+ patch_target_info_t *) = target_info;
+
if (target->has_text_changes
|| target->added
|| target->deleted)
- SVN_ERR(install_patched_target(target, btn->abs_wc_path,
- btn->ctx, btn->dry_run,
- iterpool));
-
- if (target->has_prop_changes)
- SVN_ERR(install_patched_prop_targets(target, btn->ctx,
- btn->dry_run,
- iterpool));
+ SVN_ERR(install_patched_target(target, abs_wc_path,
+ ctx, dry_run, iterpool));
+
+ if (target->has_prop_changes && (!target->deleted))
+ SVN_ERR(install_patched_prop_targets(target, ctx,
+ dry_run, iterpool));
- SVN_ERR(write_out_rejected_hunks(target, btn->dry_run,
- iterpool));
+ SVN_ERR(write_out_rejected_hunks(target, dry_run, iterpool));
}
- SVN_ERR(send_patch_notification(target, btn->ctx, iterpool));
+ SVN_ERR(send_patch_notification(target, ctx, iterpool));
}
}
}
while (patch);
/* Delete directories which are empty after patching, if any. */
- SVN_ERR(delete_empty_dirs(targets_info, btn->ctx, btn->dry_run,
- scratch_pool));
+ SVN_ERR(delete_empty_dirs(targets_info, ctx, dry_run, scratch_pool));
SVN_ERR(svn_diff_close_patch_file(patch_file, iterpool));
svn_pool_destroy(iterpool);
@@ -2950,7 +2942,6 @@ svn_client_patch(const char *patch_abspa
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
- apply_patches_baton_t baton;
svn_node_kind_t kind;
if (strip_count < 0)
@@ -2987,19 +2978,10 @@ svn_client_patch(const char *patch_abspa
svn_dirent_local_style(wc_dir_abspath,
scratch_pool));
- baton.patch_abspath = patch_abspath;
- baton.abs_wc_path = wc_dir_abspath;
- baton.dry_run = dry_run;
- baton.ctx = ctx;
- baton.strip_count = strip_count;
- baton.reverse = reverse;
- baton.ignore_whitespace = ignore_whitespace;
- baton.remove_tempfiles = remove_tempfiles;
- baton.patch_func = patch_func;
- baton.patch_baton = patch_baton;
-
- return svn_error_trace(
- svn_wc__call_with_write_lock(apply_patches, &baton,
- ctx->wc_ctx, wc_dir_abspath, FALSE,
- scratch_pool, scratch_pool));
+ SVN_WC__CALL_WITH_WRITE_LOCK(
+ apply_patches(patch_abspath, wc_dir_abspath, dry_run, strip_count,
+ reverse, ignore_whitespace, remove_tempfiles,
+ patch_func, patch_baton, ctx, scratch_pool),
+ ctx->wc_ctx, wc_dir_abspath, FALSE /* lock_anchor */, scratch_pool);
+ return SVN_NO_ERROR;
}
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/prop_commands.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/prop_commands.c Fri Jan 13 21:40:26 2012
@@ -117,7 +117,8 @@ get_file_for_validation(const svn_string
static
svn_error_t *
-do_url_propset(const char *propname,
+do_url_propset(const char *url,
+ const char *propname,
const svn_string_t *propval,
const svn_node_kind_t kind,
const svn_revnum_t base_revision_for_url,
@@ -133,8 +134,10 @@ do_url_propset(const char *propname,
if (kind == svn_node_file)
{
void *file_baton;
- SVN_ERR(editor->open_file("", root_baton, base_revision_for_url,
- pool, &file_baton));
+ const char *uri_basename = svn_uri_basename(url, pool);
+
+ SVN_ERR(editor->open_file(uri_basename, root_baton,
+ base_revision_for_url, pool, &file_baton));
SVN_ERR(editor->change_file_prop(file_baton, propname, propval, pool));
SVN_ERR(editor->close_file(file_baton, NULL, pool));
}
@@ -186,6 +189,18 @@ propset_on_url(const char *propname,
_("Path '%s' does not exist in revision %ld"),
target, base_revision_for_url);
+ if (node_kind == svn_node_file)
+ {
+ /* We need to reparent our session one directory up, since editor
+ semantics require the root is a directory.
+
+ ### How does this interact with authz? */
+ const char *parent_url;
+ parent_url = svn_uri_dirname(target, pool);
+
+ SVN_ERR(svn_ra_reparent(ra_session, parent_url, pool));
+ }
+
/* Setting an inappropriate property is not allowed (unless
overridden by 'skip_checks', in some circumstances). Deleting an
inappropriate property is allowed, however, since older clients
@@ -234,8 +249,8 @@ propset_on_url(const char *propname,
NULL, TRUE, /* No lock tokens */
pool));
- err = do_url_propset(propname, propval, node_kind, base_revision_for_url,
- editor, edit_baton, pool);
+ err = do_url_propset(target, propname, propval, node_kind,
+ base_revision_for_url, editor, edit_baton, pool);
if (err)
{
@@ -248,37 +263,6 @@ propset_on_url(const char *propname,
return editor->close_edit(edit_baton, pool);
}
-/* Baton for set_props_cb */
-struct set_props_baton
-{
- svn_client_ctx_t *ctx;
- const char *local_abspath;
- svn_depth_t depth;
- svn_node_kind_t kind;
- const char *propname;
- const svn_string_t *propval;
- svn_boolean_t skip_checks;
- const apr_array_header_t *changelist_filter;
-};
-
-/* Working copy lock callback for svn_client_propset4 */
-static svn_error_t *
-set_props_cb(void *baton,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- struct set_props_baton *bt = baton;
-
- SVN_ERR(svn_wc_prop_set4(bt->ctx->wc_ctx, bt->local_abspath, bt->propname,
- bt->propval, bt->depth, bt->skip_checks,
- bt->changelist_filter,
- bt->ctx->cancel_func, bt->ctx->cancel_baton,
- bt->ctx->notify_func2, bt->ctx->notify_baton2,
- scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
/* Check that PROPNAME is a valid name for a versioned property. Return an
* error if it is not valid, specifically if it is:
* - the name of a standard Subversion rev-prop; or
@@ -342,7 +326,6 @@ svn_client_propset_local(const char *pro
svn_node_kind_t kind;
const char *target_abspath;
svn_error_t *err;
- struct set_props_baton baton;
const char *target = APR_ARRAY_IDX(targets, i, const char *);
svn_pool_clear(iterpool);
@@ -374,18 +357,12 @@ svn_client_propset_local(const char *pro
else
SVN_ERR(err);
- baton.ctx = ctx;
- baton.local_abspath = target_abspath;
- baton.depth = depth;
- baton.kind = kind;
- baton.propname = propname;
- baton.propval = propval;
- baton.skip_checks = skip_checks;
- baton.changelist_filter = changelists;
-
- SVN_ERR(svn_wc__call_with_write_lock(set_props_cb, &baton,
- ctx->wc_ctx, target_abspath,
- FALSE, iterpool, iterpool));
+ SVN_WC__CALL_WITH_WRITE_LOCK(
+ svn_wc_prop_set4(ctx->wc_ctx, target_abspath, propname,
+ propval, depth, skip_checks, changelists,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2, iterpool),
+ ctx->wc_ctx, target_abspath, FALSE /* lock_anchor */, iterpool);
}
svn_pool_destroy(iterpool);
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/ra.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/ra.c Fri Jan 13 21:40:26 2012
@@ -40,6 +40,7 @@
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
+#include "private/svn_client_private.h"
/* This is the baton that we pass svn_ra_open3(), and is associated with
@@ -368,7 +369,7 @@ svn_client__open_ra_session_internal(svn
}
return SVN_NO_ERROR;
- }
+}
#undef SVN_CLIENT__MAX_REDIRECT_ATTEMPTS
@@ -385,54 +386,65 @@ svn_client_open_ra_session(svn_ra_sessio
}
-svn_error_t *
-svn_client_uuid_from_url(const char **uuid,
- const char *url,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
-{
- svn_ra_session_t *ra_session;
- apr_pool_t *subpool = svn_pool_create(pool);
-
- /* use subpool to create a temporary RA session */
- SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url,
- NULL, /* no base dir */
- NULL, FALSE, TRUE,
- ctx, subpool));
-
- SVN_ERR(svn_ra_get_uuid2(ra_session, uuid, pool));
-
- /* destroy the RA session */
- svn_pool_destroy(subpool);
+
- return SVN_NO_ERROR;
-}
+/* Given PATH_OR_URL, which contains either a working copy path or an
+ absolute URL, a peg revision PEG_REVISION, and a desired revision
+ REVISION, find the path at which that object exists in REVISION,
+ following copy history if necessary. If REVISION is younger than
+ PEG_REVISION, then check that PATH_OR_URL is the same node in both
+ PEG_REVISION and REVISION, and return @c
+ SVN_ERR_CLIENT_UNRELATED_RESOURCES if it is not the same node.
+
+ If PEG_REVISION->kind is 'unspecified', the peg revision is 'head'
+ for a URL or 'working' for a WC path. If REVISION->kind is
+ 'unspecified', the operative revision is the peg revision.
+
+ 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.
+
+ RA_SESSION should be an open RA session pointing at the URL of
+ PATH_OR_URL, or NULL, in which case this function will open its own
+ temporary session.
+ Use authentication baton cached in CTX to authenticate against the
+ repository.
-svn_error_t *
-svn_client_uuid_from_path2(const char **uuid,
- const char *local_abspath,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+ Use POOL for all allocations. */
+static svn_error_t *
+resolve_rev_and_url(svn_revnum_t *rev_p,
+ const char **url_p,
+ svn_ra_session_t *ra_session,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
- return svn_error_trace(
- svn_wc__node_get_repos_info(NULL, uuid, ctx->wc_ctx, local_abspath,
- result_pool, scratch_pool));
-}
+ svn_opt_revision_t peg_rev = *peg_revision;
+ svn_opt_revision_t start_rev = *revision;
+ const char *url;
+ svn_revnum_t rev;
+ /* Default revisions: peg -> working or head; operative -> peg. */
+ SVN_ERR(svn_opt_resolve_revisions(&peg_rev, &start_rev,
+ svn_path_is_url(path_or_url),
+ TRUE /* notice_local_mods */,
+ pool));
-
+ /* Run the history function to get the object's (possibly
+ different) url in REVISION. */
+ SVN_ERR(svn_client__repos_locations(&url, &rev, NULL, NULL,
+ ra_session, path_or_url, &peg_rev,
+ &start_rev, NULL, ctx, pool));
+
+ if (rev_p)
+ *rev_p = rev;
+ if (url_p)
+ *url_p = url;
-/* Convert a path or URL for display: if it is a local path, convert it to
- * the local path style; if it is a URL, return it unchanged. */
-static const char *
-path_or_url_local_style(const char *path_or_url,
- apr_pool_t *pool)
-{
- if (svn_path_is_url(path_or_url))
- return path_or_url;
- return svn_dirent_local_style(path_or_url, pool);
+ return SVN_NO_ERROR;
}
svn_error_t *
@@ -441,19 +453,15 @@ svn_client__ra_session_from_path(svn_ra_
const char **url_p,
const char *path_or_url,
const char *base_dir_abspath,
- const svn_opt_revision_t *peg_revision_p,
+ const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_ra_session_t *ra_session;
- const char *initial_url, *url;
- svn_opt_revision_t *good_rev;
- svn_opt_revision_t peg_revision, start_rev;
- svn_opt_revision_t dead_end_rev;
- svn_opt_revision_t *ignored_rev;
- svn_revnum_t rev;
- const char *ignored_url, *corrected_url;
+ const char *initial_url;
+ const char *corrected_url;
+ const char *resolved_url;
SVN_ERR(svn_client_url_from_path2(&initial_url, path_or_url, ctx, pool,
pool));
@@ -461,13 +469,6 @@ svn_client__ra_session_from_path(svn_ra_
return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
_("'%s' has no URL"), path_or_url);
- start_rev = *revision;
- peg_revision = *peg_revision_p;
- SVN_ERR(svn_opt_resolve_revisions(&peg_revision, &start_rev,
- svn_path_is_url(path_or_url),
- TRUE,
- pool));
-
SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
initial_url,
base_dir_abspath, NULL,
@@ -479,30 +480,16 @@ svn_client__ra_session_from_path(svn_ra_
if (corrected_url && svn_path_is_url(path_or_url))
path_or_url = corrected_url;
- dead_end_rev.kind = svn_opt_revision_unspecified;
-
- /* Run the history function to get the object's (possibly
- different) url in REVISION. */
- SVN_ERR(svn_client__repos_locations(&url, &good_rev,
- &ignored_url, &ignored_rev,
- ra_session,
- path_or_url, &peg_revision,
- /* search range: */
- &start_rev, &dead_end_rev,
- ctx, pool));
+ SVN_ERR(resolve_rev_and_url(rev_p, &resolved_url, ra_session,
+ path_or_url, peg_revision, revision,
+ ctx, pool));
/* Make the session point to the real URL. */
- SVN_ERR(svn_ra_reparent(ra_session, url, pool));
-
- /* Resolve good_rev into a real revnum. */
- if (good_rev->kind == svn_opt_revision_unspecified)
- good_rev->kind = svn_opt_revision_head;
- SVN_ERR(svn_client__get_revision_number(&rev, NULL, ctx->wc_ctx, url,
- ra_session, good_rev, pool));
+ SVN_ERR(svn_ra_reparent(ra_session, resolved_url, pool));
*ra_session_p = ra_session;
- *rev_p = rev;
- *url_p = url;
+ if (url_p)
+ *url_p = resolved_url;
return SVN_NO_ERROR;
}
@@ -514,7 +501,6 @@ svn_client__ensure_ra_session_url(const
const char *session_url,
apr_pool_t *pool)
{
- *old_session_url = NULL;
SVN_ERR(svn_ra_get_session_url(ra_session, old_session_url, pool));
if (! session_url)
SVN_ERR(svn_ra_get_repos_root2(ra_session, &session_url, pool));
@@ -565,7 +551,7 @@ compare_segments(const void *a, const vo
svn_error_t *
svn_client__repos_location_segments(apr_array_header_t **segments,
svn_ra_session_t *ra_session,
- const char *path,
+ const char *url,
svn_revnum_t peg_revision,
svn_revnum_t start_revision,
svn_revnum_t end_revision,
@@ -573,25 +559,131 @@ svn_client__repos_location_segments(apr_
apr_pool_t *pool)
{
struct gls_receiver_baton_t gls_receiver_baton;
+ const char *old_session_url;
+
*segments = apr_array_make(pool, 8, sizeof(svn_location_segment_t *));
gls_receiver_baton.segments = *segments;
gls_receiver_baton.ctx = ctx;
gls_receiver_baton.pool = pool;
- SVN_ERR(svn_ra_get_location_segments(ra_session, path, peg_revision,
+ SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
+ url, pool));
+ SVN_ERR(svn_ra_get_location_segments(ra_session, "", peg_revision,
start_revision, end_revision,
gls_receiver, &gls_receiver_baton,
pool));
+ SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
qsort((*segments)->elts, (*segments)->nelts,
(*segments)->elt_size, compare_segments);
return SVN_NO_ERROR;
}
+/* Set *START_URL and *END_URL to the URLs that the object URL@PEG_REVNUM
+ * had in revisions START_REVNUM and END_REVNUM. Return an error if the
+ * node cannot be traced back to one of the requested revisions.
+ *
+ * START_URL and/or END_URL may be NULL if not wanted. START_REVNUM and
+ * END_REVNUM must be valid revision numbers except that END_REVNUM may
+ * be SVN_INVALID_REVNUM if END_URL is NULL.
+ *
+ * RA_SESSION is an open RA session parented at URL.
+ */
+static svn_error_t *
+repos_locations(const char **start_url,
+ const char **end_url,
+ svn_ra_session_t *ra_session,
+ const char *url,
+ svn_revnum_t peg_revnum,
+ svn_revnum_t start_revnum,
+ svn_revnum_t end_revnum,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *repos_url, *start_path, *end_path;
+ apr_array_header_t *revs;
+ apr_hash_t *rev_locs;
+
+ SVN_ERR_ASSERT(peg_revnum != SVN_INVALID_REVNUM);
+ SVN_ERR_ASSERT(start_revnum != SVN_INVALID_REVNUM);
+ SVN_ERR_ASSERT(end_revnum != SVN_INVALID_REVNUM || end_url == NULL);
+
+ /* Avoid a network request in the common easy case. */
+ if (start_revnum == peg_revnum
+ && (end_revnum == peg_revnum || end_revnum == SVN_INVALID_REVNUM))
+ {
+ if (start_url)
+ *start_url = apr_pstrdup(result_pool, url);
+ if (end_url)
+ *end_url = apr_pstrdup(result_pool, url);
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, scratch_pool));
+
+ revs = apr_array_make(scratch_pool, 2, sizeof(svn_revnum_t));
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum;
+ if (end_revnum != start_revnum && end_revnum != SVN_INVALID_REVNUM)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = end_revnum;
+
+ SVN_ERR(svn_ra_get_locations(ra_session, &rev_locs, "", peg_revnum,
+ revs, scratch_pool));
+
+ /* We'd better have all the paths we were looking for! */
+ if (start_url)
+ {
+ start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(svn_revnum_t));
+ if (! start_path)
+ return svn_error_createf
+ (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
+ _("Unable to find repository location for '%s' in revision %ld"),
+ url, start_revnum);
+ *start_url = svn_path_url_add_component2(repos_url, start_path + 1,
+ result_pool);
+ }
+
+ if (end_url)
+ {
+ end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t));
+ if (! end_path)
+ return svn_error_createf
+ (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
+ _("The location for '%s' for revision %ld does not exist in the "
+ "repository or refers to an unrelated object"),
+ url, end_revnum);
+
+ *end_url = svn_path_url_add_component2(repos_url, end_path + 1,
+ result_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__repos_location(const char **op_url,
+ svn_ra_session_t *ra_session,
+ const char *peg_url,
+ svn_revnum_t peg_revnum,
+ svn_revnum_t op_revnum,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *old_session_url;
+
+ SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
+ peg_url, scratch_pool));
+ SVN_ERR(repos_locations(op_url, NULL,
+ ra_session, peg_url, peg_revnum,
+ op_revnum, SVN_INVALID_REVNUM,
+ result_pool, scratch_pool));
+ SVN_ERR(svn_ra_reparent(ra_session, old_session_url, scratch_pool));
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_client__repos_locations(const char **start_url,
- svn_opt_revision_t **start_revision,
+ svn_revnum_t *start_revision,
const char **end_url,
- svn_opt_revision_t **end_revision,
+ svn_revnum_t *end_revision,
svn_ra_session_t *ra_session,
const char *path,
const svn_opt_revision_t *revision,
@@ -600,16 +692,11 @@ svn_client__repos_locations(const char *
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
- const char *repos_url;
const char *url;
- const char *start_path = NULL;
- const char *end_path = NULL;
const char *local_abspath_or_url;
svn_revnum_t peg_revnum = SVN_INVALID_REVNUM;
svn_revnum_t start_revnum, end_revnum;
svn_revnum_t youngest_rev = SVN_INVALID_REVNUM;
- apr_array_header_t *revs;
- apr_hash_t *rev_locs;
apr_pool_t *subpool = svn_pool_create(pool);
/* Ensure that we are given some real revision data to work with.
@@ -619,9 +706,17 @@ svn_client__repos_locations(const char *
|| start->kind == svn_opt_revision_unspecified)
return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL);
- /* Check to see if this is schedule add with history working copy
- path. If it is, then we need to use the URL and peg revision of
- the copyfrom information. */
+ if (end == NULL)
+ {
+ static const svn_opt_revision_t unspecified_rev
+ = { svn_opt_revision_unspecified, { 0 } };
+
+ end = &unspecified_rev;
+ }
+
+ /* Determine LOCAL_ABSPATH_OR_URL, URL, and possibly PEG_REVNUM.
+ If we are looking at the working version of a WC path that is scheduled
+ as a copy, then we need to use the copy-from URL and peg revision. */
if (! svn_path_is_url(path))
{
SVN_ERR(svn_dirent_get_absolute(&local_abspath_or_url, path, subpool));
@@ -633,7 +728,7 @@ svn_client__repos_locations(const char *
svn_boolean_t is_copy;
SVN_ERR(svn_wc__node_get_origin(&is_copy, &peg_revnum, &repos_relpath,
- &repos_root_url, NULL,
+ &repos_root_url, NULL, NULL,
ctx->wc_ctx, local_abspath_or_url,
FALSE, subpool, subpool));
@@ -703,100 +798,65 @@ svn_client__repos_locations(const char *
ra_session, end, pool));
/* Set the output revision variables. */
- *start_revision = apr_pcalloc(pool, sizeof(**start_revision));
- (*start_revision)->kind = svn_opt_revision_number;
- (*start_revision)->value.number = start_revnum;
- if (end->kind != svn_opt_revision_unspecified)
- {
- *end_revision = apr_pcalloc(pool, sizeof(**end_revision));
- (*end_revision)->kind = svn_opt_revision_number;
- (*end_revision)->value.number = end_revnum;
- }
-
- if (start_revnum == peg_revnum && end_revnum == peg_revnum)
- {
- /* Avoid a network request in the common easy case. */
- *start_url = url;
- if (end->kind != svn_opt_revision_unspecified)
- *end_url = url;
- svn_pool_destroy(subpool);
- return SVN_NO_ERROR;
+ if (start_revision)
+ {
+ *start_revision = start_revnum;
+ }
+ if (end_revision && end->kind != svn_opt_revision_unspecified)
+ {
+ *end_revision = end_revnum;
}
- SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, subpool));
-
- revs = apr_array_make(subpool, 2, sizeof(svn_revnum_t));
- APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum;
- if (end_revnum != start_revnum)
- APR_ARRAY_PUSH(revs, svn_revnum_t) = end_revnum;
-
- SVN_ERR(svn_ra_get_locations(ra_session, &rev_locs, "", peg_revnum,
- revs, subpool));
-
- /* We'd better have all the paths we were looking for! */
- start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(svn_revnum_t));
- if (! start_path)
- return svn_error_createf
- (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
- _("Unable to find repository location for '%s' in revision %ld"),
- path_or_url_local_style(path, pool), start_revnum);
-
- end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t));
- if (! end_path)
- return svn_error_createf
- (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
- _("The location for '%s' for revision %ld does not exist in the "
- "repository or refers to an unrelated object"),
- path_or_url_local_style(path, pool), end_revnum);
-
- /* Set our return variables */
- *start_url = svn_path_url_add_component2(repos_url, start_path + 1, pool);
- if (end->kind != svn_opt_revision_unspecified)
- *end_url = svn_path_url_add_component2(repos_url, end_path + 1, pool);
-
+ SVN_ERR(repos_locations(start_url, end_url,
+ ra_session, url, peg_revnum,
+ start_revnum, end_revnum,
+ pool, subpool));
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
svn_error_t *
-svn_client__get_youngest_common_ancestor(const char **ancestor_path,
+svn_client__get_youngest_common_ancestor(const char **ancestor_relpath,
+ const char **ancestor_url,
svn_revnum_t *ancestor_revision,
- const char *path_or_url1,
+ const char *url1,
svn_revnum_t rev1,
- const char *path_or_url2,
+ const char *url2,
svn_revnum_t rev2,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
+ apr_pool_t *sesspool = svn_pool_create(pool);
+ svn_ra_session_t *session;
+ const char *repos_root_url;
apr_hash_t *history1, *history2;
apr_hash_index_t *hi;
svn_revnum_t yc_revision = SVN_INVALID_REVNUM;
- const char *yc_path = NULL;
- svn_opt_revision_t revision1, revision2;
+ const char *yc_relpath = NULL;
svn_boolean_t has_rev_zero_history1;
svn_boolean_t has_rev_zero_history2;
- revision1.kind = revision2.kind = svn_opt_revision_number;
- revision1.value.number = rev1;
- revision2.value.number = rev2;
+ /* Open an RA session for the two locations. */
+ SVN_ERR(svn_client_open_ra_session(&session, url1, ctx, sesspool));
+ SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, pool));
/* We're going to cheat and use history-as-mergeinfo because it
saves us a bunch of annoying custom data comparisons and such. */
SVN_ERR(svn_client__get_history_as_mergeinfo(&history1,
&has_rev_zero_history1,
- path_or_url1,
- &revision1,
+ url1, rev1,
SVN_INVALID_REVNUM,
SVN_INVALID_REVNUM,
- NULL, ctx, pool));
+ session, ctx, pool));
SVN_ERR(svn_client__get_history_as_mergeinfo(&history2,
&has_rev_zero_history2,
- path_or_url2,
- &revision2,
+ url2, rev2,
SVN_INVALID_REVNUM,
SVN_INVALID_REVNUM,
- NULL, ctx, pool));
+ session, ctx, pool));
+ /* Close the source and target sessions. */
+ svn_pool_destroy(sesspool);
/* Loop through the first location's history, check for overlapping
paths and ranges in the second location's history, and
@@ -823,7 +883,7 @@ svn_client__get_youngest_common_ancestor
|| (yc_range->end > yc_revision))
{
yc_revision = yc_range->end;
- yc_path = path + 1;
+ yc_relpath = path + 1;
}
}
}
@@ -831,13 +891,52 @@ svn_client__get_youngest_common_ancestor
/* It's possible that PATH_OR_URL1 and PATH_OR_URL2's only common
history is revision 0. */
- if (!yc_path && has_rev_zero_history1 && has_rev_zero_history2)
+ if (!yc_relpath && has_rev_zero_history1 && has_rev_zero_history2)
{
- yc_path = "/";
+ yc_relpath = "";
yc_revision = 0;
}
- *ancestor_path = yc_path;
- *ancestor_revision = yc_revision;
+ if (ancestor_relpath)
+ *ancestor_relpath = yc_relpath;
+ if (ancestor_url)
+ *ancestor_url
+ = yc_relpath ? svn_path_url_add_component2(repos_root_url, yc_relpath,
+ pool) : NULL;
+ if (ancestor_revision)
+ *ancestor_revision = yc_revision;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__youngest_common_ancestor(const char **ancestor_url,
+ svn_revnum_t *ancestor_rev,
+ const char *path_or_url1,
+ const svn_opt_revision_t *revision1,
+ const char *path_or_url2,
+ const svn_opt_revision_t *revision2,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *sesspool = svn_pool_create(scratch_pool);
+ svn_ra_session_t *session;
+ const char *url1, *url2;
+ svn_revnum_t rev1, rev2;
+
+ /* Resolve the two locations */
+ SVN_ERR(svn_client__ra_session_from_path(&session, &rev1, &url1,
+ path_or_url1, NULL,
+ revision1, revision1,
+ ctx, sesspool));
+ SVN_ERR(resolve_rev_and_url(&rev2, &url2, session,
+ path_or_url2, revision2, revision2,
+ ctx, scratch_pool));
+
+ SVN_ERR(svn_client__get_youngest_common_ancestor(
+ NULL, ancestor_url, ancestor_rev,
+ url1, rev1, url2, rev2, ctx, result_pool));
+
+ svn_pool_destroy(sesspool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/relocate.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/relocate.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/relocate.c Fri Jan 13 21:40:26 2012
@@ -139,16 +139,13 @@ relocate_externals(const char *local_abs
apr_array_header_t *ext_desc,
const char *old_parent_repos_root_url,
const char *new_parent_repos_root_url,
+ svn_boolean_t ignore_externals,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
- const char *url;
apr_pool_t *iterpool;
int i;
- SVN_ERR(svn_client_url_from_path2(&url, local_abspath, ctx,
- scratch_pool, scratch_pool));
-
/* Parse an externals definition into an array of external items. */
iterpool = svn_pool_create(scratch_pool);
@@ -184,8 +181,8 @@ relocate_externals(const char *local_abs
ext_item->target_dir,
iterpool),
iterpool));
- err = svn_client_root_url_from_path(&target_repos_root_url,
- target_abspath, ctx, iterpool);
+ err = svn_client_get_repos_root(&target_repos_root_url, NULL /* uuid */,
+ target_abspath, ctx, iterpool, iterpool);
/* Ignore externals that aren't present in the working copy.
* This can happen if an external is deleted from disk accidentally,
@@ -202,7 +199,7 @@ relocate_externals(const char *local_abs
SVN_ERR(svn_client_relocate2(target_abspath,
old_parent_repos_root_url,
new_parent_repos_root_url,
- TRUE, ctx, iterpool));
+ ignore_externals, ctx, iterpool));
}
svn_pool_destroy(iterpool);
@@ -247,16 +244,16 @@ svn_client_relocate2(const char *wcroot_
}
/* Fetch our current root URL. */
- SVN_ERR(svn_client_root_url_from_path(&old_repos_root_url, local_abspath,
- ctx, pool));
+ SVN_ERR(svn_client_get_repos_root(&old_repos_root_url, NULL /* uuid */,
+ local_abspath, ctx, pool, pool));
/* Perform the relocation. */
SVN_ERR(svn_wc_relocate4(ctx->wc_ctx, local_abspath, from_prefix, to_prefix,
validator_func, &vb, pool));
/* Now fetch new current root URL. */
- SVN_ERR(svn_client_root_url_from_path(&new_repos_root_url, local_abspath,
- ctx, pool));
+ SVN_ERR(svn_client_get_repos_root(&new_repos_root_url, NULL /* uuid */,
+ local_abspath, ctx, pool, pool));
/* Relocate externals, too (if any). */
@@ -284,7 +281,8 @@ svn_client_relocate2(const char *wcroot_
iterpool));
if (ext_desc->nelts)
SVN_ERR(relocate_externals(this_abspath, ext_desc, old_repos_root_url,
- new_repos_root_url, ctx, iterpool));
+ new_repos_root_url, ignore_externals, ctx,
+ iterpool));
}
svn_pool_destroy(iterpool);
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/repos_diff.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/repos_diff.c Fri Jan 13 21:40:26 2012
@@ -51,14 +51,6 @@
/* Overall crawler editor baton. */
struct edit_baton {
- /* TARGET is a working-copy directory which corresponds to the base
- URL open in RA_SESSION below. */
- const char *target;
-
- /* A working copy context for TARGET, NULL if this is purely a
- repository operation. */
- svn_wc_context_t *wc_ctx;
-
/* The passed depth */
svn_depth_t depth;
@@ -140,9 +132,6 @@ struct dir_baton {
/* The path of the directory within the repository */
const char *path;
- /* The path of the directory in the wc, relative to cwd */
- const char *wcpath;
-
/* The baton for the parent directory, or null if this is the root of the
hierarchy to be compared. */
struct dir_baton *dir_baton;
@@ -179,9 +168,6 @@ struct file_baton {
/* The path of the file within the repository */
const char *path;
- /* The path of the file in the wc, relative to cwd */
- const char *wcpath;
-
/* The path and APR file handle to the temporary file that contains the
first repository version. Also, the pristine-property list of
this file. */
@@ -242,7 +228,6 @@ make_dir_baton(const char *path,
dir_baton->skip_children = FALSE;
dir_baton->pool = dir_pool;
dir_baton->path = apr_pstrdup(dir_pool, path);
- dir_baton->wcpath = svn_dirent_join(edit_baton->target, path, dir_pool);
dir_baton->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t));
return dir_baton;
@@ -268,7 +253,6 @@ make_file_baton(const char *path,
file_baton->skip = FALSE;
file_baton->pool = file_pool;
file_baton->path = apr_pstrdup(file_pool, path);
- file_baton->wcpath = svn_dirent_join(edit_baton->target, path, file_pool);
file_baton->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t));
file_baton->base_revision = edit_baton->revision;
@@ -494,38 +478,84 @@ open_root(void *edit_baton,
return SVN_NO_ERROR;
}
-/* Recursively walk tree rooted at DIR (at REVISION) in the repository,
+/* Compare a file being deleted against an empty file.
+ */
+static svn_error_t *
+diff_deleted_file(svn_wc_notify_state_t *state_p,
+ svn_boolean_t *tree_conflicted_p,
+ const char *path,
+ struct edit_baton *eb,
+ apr_pool_t *scratch_pool)
+{
+ struct file_baton *b = make_file_baton(path, FALSE, eb, scratch_pool);
+/* struct edit_baton *eb = b->edit_baton;*/
+ const char *mimetype1, *mimetype2;
+
+ if (eb->cancel_func)
+ SVN_ERR(eb->cancel_func(eb->cancel_baton));
+
+ if (eb->text_deltas)
+ SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
+ else
+ SVN_ERR(get_empty_file(eb, &b->path_start_revision));
+ SVN_ERR(get_empty_file(eb, &b->path_end_revision));
+ get_file_mime_types(&mimetype1, &mimetype2, b);
+
+ SVN_ERR(eb->diff_callbacks->file_deleted(state_p, tree_conflicted_p,
+ b->path,
+ b->path_start_revision,
+ b->path_end_revision,
+ mimetype1, mimetype2,
+ b->pristine_props,
+ eb->diff_cmd_baton,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* Recursively walk tree rooted at DIR (at EB->revision) in the repository,
* reporting all children as deleted. Part of a workaround for issue 2333.
*
- * DIR is a repository path relative to the URL in RA_SESSION. REVISION
- * must be a valid revision number, not SVN_INVALID_REVNUM. EB is the
- * overall crawler editor baton. If CANCEL_FUNC is not NULL, then it
- * should refer to a cancellation function (along with CANCEL_BATON).
+ * DIR is a repository path relative to the URL in EB->ra_session. EB is
+ * the overall crawler editor baton. EB->revision must be a valid revision
+ * number, not SVN_INVALID_REVNUM. Use EB->cancel_func (if not null) with
+ * EB->cancel_baton for cancellation.
*/
/* ### TODO: Handle depth. */
static svn_error_t *
-diff_deleted_dir(const char *dir,
- svn_revnum_t revision,
- svn_ra_session_t *ra_session,
+diff_deleted_dir(svn_wc_notify_state_t *state_p,
+ svn_boolean_t *tree_conflicted_p,
+ const char *dir,
struct edit_baton *eb,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
apr_pool_t *pool)
{
apr_hash_t *dirents;
apr_pool_t *iterpool = svn_pool_create(pool);
apr_hash_index_t *hi;
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(eb->revision));
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
+ if (eb->cancel_func)
+ SVN_ERR(eb->cancel_func(eb->cancel_baton));
- SVN_ERR(svn_ra_get_dir2(ra_session,
+ SVN_ERR(eb->diff_callbacks->dir_deleted(
+ state_p, tree_conflicted_p, dir,
+ eb->diff_cmd_baton, pool));
+
+ /* The "old" dir will be skipped by the repository report. If required,
+ * crawl it recursively, diffing each file against the empty file. This
+ * is a workaround for issue 2333 "'svn diff URL1 URL2' not reverse of
+ * 'svn diff URL2 URL1'". */
+ if (! eb->walk_deleted_repos_dirs)
+ {
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session,
&dirents,
NULL, NULL,
dir,
- revision,
+ eb->revision,
SVN_DIRENT_KIND,
pool));
@@ -542,44 +572,12 @@ diff_deleted_dir(const char *dir,
if (dirent->kind == svn_node_file)
{
- struct file_baton *b;
- const char *mimetype1, *mimetype2;
-
- /* Compare a file being deleted against an empty file */
- b = make_file_baton(path, FALSE, eb, iterpool);
- if (eb->text_deltas)
- SVN_ERR(get_file_from_ra(b, FALSE, iterpool));
- else
- SVN_ERR(get_empty_file(eb, &b->path_start_revision));
-
- SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision)));
-
- get_file_mime_types(&mimetype1, &mimetype2, b);
-
- SVN_ERR(eb->diff_callbacks->file_deleted(
- NULL, NULL, b->wcpath,
- b->path_start_revision,
- b->path_end_revision,
- mimetype1, mimetype2,
- b->pristine_props,
- b->edit_baton->diff_cmd_baton,
- iterpool));
+ SVN_ERR(diff_deleted_file(NULL, NULL, path, eb, iterpool));
}
if (dirent->kind == svn_node_dir)
{
- const char *wcpath = svn_dirent_join(eb->target, path, iterpool);
-
- SVN_ERR(eb->diff_callbacks->dir_deleted(
- NULL, NULL, wcpath,
- eb->diff_cmd_baton, iterpool));
- SVN_ERR(diff_deleted_dir(path,
- revision,
- ra_session,
- eb,
- cancel_func,
- cancel_baton,
- iterpool));
+ SVN_ERR(diff_deleted_dir(NULL, NULL, path, eb, iterpool));
}
}
@@ -617,51 +615,14 @@ delete_entry(const char *path,
{
case svn_node_file:
{
- const char *mimetype1, *mimetype2;
- struct file_baton *b;
-
- /* Compare a file being deleted against an empty file */
- b = make_file_baton(path, FALSE, eb, scratch_pool);
- if (eb->text_deltas)
- SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
- else
- SVN_ERR(get_empty_file(eb, &b->path_start_revision));
-
- SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision)));
-
- get_file_mime_types(&mimetype1, &mimetype2, b);
-
- SVN_ERR(eb->diff_callbacks->file_deleted(
- &state, &tree_conflicted, b->wcpath,
- b->path_start_revision,
- b->path_end_revision,
- mimetype1, mimetype2,
- b->pristine_props,
- b->edit_baton->diff_cmd_baton,
- scratch_pool));
-
+ SVN_ERR(diff_deleted_file(&state, &tree_conflicted, path, eb,
+ scratch_pool));
break;
}
case svn_node_dir:
{
- SVN_ERR(eb->diff_callbacks->dir_deleted(
- &state, &tree_conflicted,
- svn_dirent_join(eb->target, path, pool),
- eb->diff_cmd_baton, scratch_pool));
-
- if (eb->walk_deleted_repos_dirs)
- {
- /* A workaround for issue 2333. The "old" dir will be
- skipped by the repository report. Crawl it recursively,
- diffing each file against the empty file. */
- SVN_ERR(diff_deleted_dir(path,
- eb->revision,
- eb->ra_session,
- eb,
- eb->cancel_func,
- eb->cancel_baton,
- scratch_pool));
- }
+ SVN_ERR(diff_deleted_dir(&state, &tree_conflicted, path, eb,
+ scratch_pool));
break;
}
default:
@@ -677,9 +638,9 @@ delete_entry(const char *path,
if (eb->notify_func)
{
- const char* deleted_path;
+ const char *deleted_path = apr_pstrdup(eb->pool, path);
deleted_path_notify_t *dpn = apr_pcalloc(eb->pool, sizeof(*dpn));
- deleted_path = svn_dirent_join(eb->target, path, eb->pool);
+
dpn->kind = kind;
dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action;
dpn->state = state;
@@ -723,7 +684,7 @@ add_directory(const char *path,
SVN_ERR(eb->diff_callbacks->dir_added(
&state, &b->tree_conflicted,
- &b->skip, &b->skip_children, b->wcpath,
+ &b->skip, &b->skip_children, b->path,
eb->target_revision, copyfrom_path, copyfrom_revision,
eb->diff_cmd_baton, pool));
@@ -742,12 +703,12 @@ add_directory(const char *path,
/* Find out if a pending delete notification for this path is
* still around. */
- dpn = apr_hash_get(eb->deleted_paths, b->wcpath, APR_HASH_KEY_STRING);
+ dpn = apr_hash_get(eb->deleted_paths, b->path, APR_HASH_KEY_STRING);
if (dpn)
{
/* If any was found, we will handle the pending 'deleted path
* notification' (DPN) here. Remove it from the list. */
- apr_hash_set(eb->deleted_paths, b->wcpath,
+ apr_hash_set(eb->deleted_paths, b->path,
APR_HASH_KEY_STRING, NULL);
/* the pending delete might be on a different node kind. */
@@ -773,7 +734,7 @@ add_directory(const char *path,
else
action = svn_wc_notify_update_add;
- notify = svn_wc_create_notify(b->wcpath, action, pool);
+ notify = svn_wc_create_notify(b->path, action, pool);
notify->kind = kind;
notify->content_state = notify->prop_state = state;
(*eb->notify_func)(eb->notify_baton, notify, pool);
@@ -809,7 +770,7 @@ open_directory(const char *path,
SVN_ERR(eb->diff_callbacks->dir_opened(
&b->tree_conflicted, &b->skip,
- &b->skip_children, b->wcpath, base_revision,
+ &b->skip_children, b->path, base_revision,
b->edit_baton->diff_cmd_baton, pool));
return SVN_NO_ERROR;
@@ -872,7 +833,7 @@ open_file(const char *path,
SVN_ERR(eb->diff_callbacks->file_opened(
&b->tree_conflicted, &b->skip,
- b->wcpath, base_revision, eb->diff_cmd_baton, pool));
+ b->path, base_revision, eb->diff_cmd_baton, pool));
return SVN_NO_ERROR;
}
@@ -1043,7 +1004,7 @@ close_file(void *file_baton,
if (b->added)
SVN_ERR(eb->diff_callbacks->file_added(
&content_state, &prop_state, &b->tree_conflicted,
- b->wcpath,
+ b->path,
b->path_end_revision ? b->path_start_revision : NULL,
b->path_end_revision,
0,
@@ -1056,7 +1017,7 @@ close_file(void *file_baton,
else
SVN_ERR(eb->diff_callbacks->file_changed(
&content_state, &prop_state,
- &b->tree_conflicted, b->wcpath,
+ &b->tree_conflicted, b->path,
b->path_end_revision ? b->path_start_revision : NULL,
b->path_end_revision,
b->edit_baton->revision,
@@ -1074,16 +1035,15 @@ close_file(void *file_baton,
svn_wc_notify_t *notify;
svn_wc_notify_action_t action;
svn_node_kind_t kind = svn_node_file;
- const char *moved_to_abspath = NULL;
/* Find out if a pending delete notification for this path is
* still around. */
- dpn = apr_hash_get(eb->deleted_paths, b->wcpath, APR_HASH_KEY_STRING);
+ dpn = apr_hash_get(eb->deleted_paths, b->path, APR_HASH_KEY_STRING);
if (dpn)
{
/* If any was found, we will handle the pending 'deleted path
* notification' (DPN) here. Remove it from the list. */
- apr_hash_set(eb->deleted_paths, b->wcpath,
+ apr_hash_set(eb->deleted_paths, b->path,
APR_HASH_KEY_STRING, NULL);
/* the pending delete might be on a different node kind. */
@@ -1110,30 +1070,9 @@ close_file(void *file_baton,
else if (b->added)
action = svn_wc_notify_update_add;
else
- {
- svn_error_t *err;
-
- action = svn_wc_notify_update_update;
-
- /* If the file was moved-away, use its new path in the
- * notification.
- * ### This is redundant. The file_changed() callback should
- * ### pass the moved-to path back up here. */
- err = svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
- eb->wc_ctx, b->wcpath,
- scratch_pool, scratch_pool);
- if (err)
- {
- if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- svn_error_clear(err);
- else
- return svn_error_trace(err);
- }
- }
+ action = svn_wc_notify_update_update;
- notify = svn_wc_create_notify(moved_to_abspath ? moved_to_abspath
- : b->wcpath,
- action, scratch_pool);
+ notify = svn_wc_create_notify(b->path, action, scratch_pool);
notify->kind = kind;
notify->content_state = content_state;
notify->prop_state = prop_state;
@@ -1181,7 +1120,7 @@ close_directory(void *dir_baton,
svn_boolean_t tree_conflicted = FALSE;
SVN_ERR(eb->diff_callbacks->dir_props_changed(
&prop_state, &tree_conflicted,
- b->wcpath, b->added,
+ b->path, b->added,
b->propchanges, b->pristine_props,
b->edit_baton->diff_cmd_baton, scratch_pool));
if (tree_conflicted)
@@ -1196,7 +1135,7 @@ close_directory(void *dir_baton,
}
SVN_ERR(eb->diff_callbacks->dir_closed(NULL, NULL, NULL,
- b->wcpath, b->added,
+ b->path, b->added,
b->edit_baton->diff_cmd_baton,
scratch_pool));
@@ -1237,7 +1176,7 @@ close_directory(void *dir_baton,
else
action = svn_wc_notify_update_update;
- notify = svn_wc_create_notify(b->wcpath, action, pool);
+ notify = svn_wc_create_notify(b->path, action, pool);
notify->kind = svn_node_dir;
/* In case of a tree conflict during merge, the diff callback
@@ -1330,11 +1269,8 @@ absent_directory(const char *path,
if (eb->notify_func)
{
svn_wc_notify_t *notify
- = svn_wc_create_notify(svn_dirent_join(pb->wcpath,
- svn_relpath_basename(path,
- NULL),
- pool),
- svn_wc_notify_skip, pool);
+ = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
+
notify->kind = svn_node_dir;
notify->content_state = notify->prop_state
= svn_wc_notify_state_missing;
@@ -1360,11 +1296,8 @@ absent_file(const char *path,
if (eb->notify_func)
{
svn_wc_notify_t *notify
- = svn_wc_create_notify(svn_dirent_join(pb->wcpath,
- svn_relpath_basename(path,
- pool),
- pool),
- svn_wc_notify_skip, pool);
+ = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
+
notify->kind = svn_node_file;
notify->content_state = notify->prop_state
= svn_wc_notify_state_missing;
@@ -1374,12 +1307,100 @@ absent_file(const char *path,
return SVN_NO_ERROR;
}
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *scratch_pool)
+{
+ struct edit_baton *eb = baton;
+ svn_node_kind_t node_kind;
+
+ SVN_ERR(svn_ra_check_path(eb->ra_session, path, eb->revision, &node_kind,
+ scratch_pool));
+
+ *kind = svn__kind_from_node_kind(node_kind, FALSE);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct edit_baton *eb = baton;
+ svn_node_kind_t node_kind;
+
+ SVN_ERR(svn_ra_check_path(eb->ra_session, path, eb->revision, &node_kind,
+ scratch_pool));
+
+ if (node_kind == svn_node_file)
+ {
+ SVN_ERR(svn_ra_get_file(eb->ra_session, path, eb->revision,
+ NULL, NULL, props, result_pool));
+ }
+ else if (node_kind == svn_node_dir)
+ {
+ apr_array_header_t *tmp_props;
+
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, props, path,
+ eb->revision, 0 /* Dirent fields */,
+ result_pool));
+ tmp_props = svn_prop_hash_to_array(*props, result_pool);
+ SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props,
+ result_pool));
+ *props = svn_prop_array_to_hash(tmp_props, result_pool);
+ }
+ else
+ {
+ *props = apr_hash_make(result_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct edit_baton *eb = baton;
+ svn_stream_t *fstream;
+ svn_error_t *err;
+
+ SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, scratch_pool));
+
+ err = svn_ra_get_file(eb->ra_session, path, eb->revision,
+ fstream, NULL, NULL, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ SVN_ERR(svn_stream_close(fstream));
+
+ *filename = NULL;
+ return SVN_NO_ERROR;
+ }
+ else if (err)
+ return svn_error_trace(err);
+
+ SVN_ERR(svn_stream_close(fstream));
+
+ return SVN_NO_ERROR;
+}
+
/* Create a repository diff editor and baton. */
svn_error_t *
svn_client__get_diff_editor(const svn_delta_editor_t **editor,
void **edit_baton,
- svn_wc_context_t *wc_ctx,
- const char *target,
svn_depth_t depth,
svn_ra_session_t *ra_session,
svn_revnum_t revision,
@@ -1396,10 +1417,10 @@ svn_client__get_diff_editor(const svn_de
apr_pool_t *editor_pool = svn_pool_create(result_pool);
svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool);
struct edit_baton *eb = apr_pcalloc(editor_pool, sizeof(*eb));
+ svn_delta_shim_callbacks_t *shim_callbacks =
+ svn_delta_shim_callbacks_default(editor_pool);
eb->pool = editor_pool;
- eb->target = target;
- eb->wc_ctx = wc_ctx;
eb->depth = depth;
eb->diff_callbacks = diff_callbacks;
eb->diff_cmd_baton = diff_cmd_baton;
@@ -1432,11 +1453,19 @@ svn_client__get_diff_editor(const svn_de
tree_editor->absent_directory = absent_directory;
tree_editor->absent_file = absent_file;
- return svn_delta_get_cancellation_editor(cancel_func,
- cancel_baton,
- tree_editor,
- eb,
- editor,
- edit_baton,
- eb->pool);
+ SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
+ tree_editor, eb,
+ editor, edit_baton,
+ eb->pool));
+
+ shim_callbacks->fetch_kind_func = fetch_kind_func;
+ shim_callbacks->fetch_props_func = fetch_props_func;
+ shim_callbacks->fetch_base_func = fetch_base_func;
+ shim_callbacks->fetch_baton = eb;
+
+ SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
+ shim_callbacks,
+ result_pool, result_pool));
+
+ return SVN_NO_ERROR;
}
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/status.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/status.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/status.c Fri Jan 13 21:40:26 2012
@@ -430,7 +430,7 @@ svn_client_status5(svn_revnum_t *result_
pool));
}
- if (depth_as_sticky)
+ if (depth_as_sticky || !server_supports_depth)
status_depth = depth;
else
status_depth = svn_depth_unknown; /* Use depth from WC */
@@ -620,27 +620,12 @@ svn_client__create_status(svn_client_sta
(*cst)->repos_relpath = status->repos_relpath;
(*cst)->switched = status->switched;
- (*cst)->file_external = FALSE;
- if (/* Old style file-externals */
- (status->versioned
- && status->switched
- && status->kind == svn_node_file))
+ (*cst)->file_external = status->file_external;
+ if (status->file_external)
{
- svn_node_kind_t external_kind;
-
- SVN_ERR(svn_wc__read_external_info(&external_kind, NULL, NULL, NULL,
- NULL, wc_ctx,
- local_abspath /* wri_abspath */,
- local_abspath, TRUE,
- scratch_pool, scratch_pool));
-
- if (external_kind == svn_node_file)
- {
- (*cst)->file_external = TRUE;
- (*cst)->switched = FALSE;
- (*cst)->node_status = (*cst)->text_status;
- }
+ (*cst)->switched = FALSE;
+ (*cst)->node_status = (*cst)->text_status;
}
(*cst)->lock = status->lock;
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/switch.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/switch.c Fri Jan 13 21:40:26 2012
@@ -197,7 +197,7 @@ switch_internal(svn_revnum_t *result_rev
### okay? */
if (! ignore_ancestry)
{
- const char *target_url, *yc_path;
+ const char *target_url, *yc_url;
svn_revnum_t target_rev, yc_rev;
SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
@@ -206,11 +206,11 @@ switch_internal(svn_revnum_t *result_rev
local_abspath, pool));
/* ### It would be nice if this function could reuse the existing
ra session instead of opening two for its own use. */
- SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_path, &yc_rev,
+ SVN_ERR(svn_client__get_youngest_common_ancestor(NULL, &yc_url, &yc_rev,
switch_rev_url, revnum,
target_url, target_rev,
ctx, pool));
- if (! (yc_path && SVN_IS_VALID_REVNUM(yc_rev)))
+ if (! (yc_url && SVN_IS_VALID_REVNUM(yc_rev)))
return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
_("'%s' shares no common ancestry with '%s'"),
switch_url, local_abspath);
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/update.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/update.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/update.c Fri Jan 13 21:40:26 2012
@@ -83,8 +83,7 @@ svn_client__dirent_fetcher(void *baton,
*dirents = NULL;
if (old_url)
- SVN_ERR(svn_client__ensure_ra_session_url(&old_url, dfb->ra_session,
- old_url, scratch_pool));
+ SVN_ERR(svn_ra_reparent(dfb->ra_session, old_url, scratch_pool));
return SVN_NO_ERROR;
}
@@ -169,7 +168,7 @@ is_empty_wc(svn_boolean_t *clean_checkou
This is typically either the same as LOCAL_ABSPATH, or the
immediate parent of LOCAL_ABSPATH.
- If NOTIFY_SUMMARY is set (and there's a notification hander in
+ If NOTIFY_SUMMARY is set (and there's a notification handler in
CTX), transmit the final update summary upon successful
completion of the update.
*/
@@ -390,7 +389,9 @@ update_internal(svn_revnum_t *result_rev
invalid revnum, that means RA will use the latest revision. */
SVN_ERR(svn_ra_do_update2(ra_session, &reporter, &report_baton,
revnum, target,
- depth_is_sticky ? depth : svn_depth_unknown,
+ (!server_supports_depth || depth_is_sticky
+ ? depth
+ : svn_depth_unknown),
FALSE, update_editor, update_edit_baton, pool));
/* Drive the reporter structure, describing the revisions within
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/url.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/url.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/url.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/url.c Fri Jan 13 21:40:26 2012
@@ -61,18 +61,3 @@ svn_client_url_from_path2(const char **u
return SVN_NO_ERROR;
}
-
-
-svn_error_t *
-svn_client_root_url_from_path(const char **url,
- const char *path_or_url,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
-{
- if (!svn_path_is_url(path_or_url))
- SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool));
-
- return svn_error_trace(
- svn_client__get_repos_root(url, path_or_url,
- ctx, pool, pool));
-}
Modified: subversion/branches/revprop-packing/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_client/util.c?rev=1231318&r1=1231317&r2=1231318&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_client/util.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_client/util.c Fri Jan 13 21:40:26 2012
@@ -102,17 +102,15 @@ svn_client__path_relative_to_root(const
SVN_ERR_ASSERT(repos_relpath != NULL);
}
- /* Merge handling passes a root that is not the repos root */
else if (repos_root != NULL)
{
- if (!svn_uri__is_ancestor(repos_root, abspath_or_url))
+ repos_relpath = svn_uri_skip_ancestor(repos_root, abspath_or_url,
+ result_pool);
+ if (!repos_relpath)
return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
_("URL '%s' is not a child of repository "
"root URL '%s'"),
abspath_or_url, repos_root);
-
- repos_relpath = svn_uri_skip_ancestor(repos_root, abspath_or_url,
- result_pool);
}
else
{
@@ -144,18 +142,19 @@ svn_client__path_relative_to_root(const
}
svn_error_t *
-svn_client__get_repos_root(const char **repos_root,
- const char *abspath_or_url,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_client_get_repos_root(const char **repos_root,
+ const char **repos_uuid,
+ const char *abspath_or_url,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_ra_session_t *ra_session;
/* If PATH_OR_URL is a local path we can fetch the repos root locally. */
if (!svn_path_is_url(abspath_or_url))
{
- SVN_ERR(svn_wc__node_get_repos_info(repos_root, NULL,
+ SVN_ERR(svn_wc__node_get_repos_info(repos_root, repos_uuid,
ctx->wc_ctx, abspath_or_url,
result_pool, scratch_pool));
@@ -168,7 +167,10 @@ svn_client__get_repos_root(const char **
NULL, NULL, FALSE, TRUE,
ctx, scratch_pool));
- SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));
+ if (repos_root)
+ SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));
+ if (repos_uuid)
+ SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool));
return SVN_NO_ERROR;
}