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 2010/12/11 01:16:08 UTC
svn commit: r1044548 [7/39] - in /subversion/branches/ignore-mergeinfo: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/ contrib/hook-scripts/
contrib/server-side/ notes/api-errata/ notes/api-erra...
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c Sat Dec 11 00:15:55 2010
@@ -450,6 +450,53 @@ svn_client_propset4(const char *propname
}
}
+static svn_error_t *
+check_and_set_revprop(svn_revnum_t *set_rev,
+ svn_ra_session_t *ra_session,
+ const char *propname,
+ const svn_string_t *original_propval,
+ const svn_string_t *propval,
+ apr_pool_t *pool)
+{
+ if (original_propval)
+ {
+ /* Ensure old value hasn't changed behind our back. */
+ svn_string_t *current;
+ SVN_ERR(svn_ra_rev_prop(ra_session, *set_rev, propname, ¤t, pool));
+
+ if (original_propval->data && (! current))
+ {
+ return svn_error_createf(
+ SVN_ERR_RA_OUT_OF_DATE, NULL,
+ _("revprop '%s' in r%ld is unexpectedly absent "
+ "in repository (maybe someone else deleted it?)"),
+ propname, *set_rev);
+ }
+ else if (original_propval->data
+ && (! svn_string_compare(original_propval, current)))
+ {
+ return svn_error_createf(
+ SVN_ERR_RA_OUT_OF_DATE, NULL,
+ _("revprop '%s' in r%ld has unexpected value "
+ "in repository (maybe someone else changed it?)"),
+ propname, *set_rev);
+ }
+ else if ((! original_propval->data) && current)
+ {
+ return svn_error_createf(
+ SVN_ERR_RA_OUT_OF_DATE, NULL,
+ _("revprop '%s' in r%ld is unexpectedly present "
+ "in repository (maybe someone else set it?)"),
+ propname, *set_rev);
+ }
+ }
+
+ SVN_ERR(svn_ra_change_rev_prop2(ra_session, *set_rev, propname,
+ NULL, propval, pool));
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client_revprop_set2(const char *propname,
const svn_string_t *propval,
@@ -462,6 +509,7 @@ svn_client_revprop_set2(const char *prop
apr_pool_t *pool)
{
svn_ra_session_t *ra_session;
+ svn_boolean_t be_atomic;
if ((strcmp(propname, SVN_PROP_REVISION_AUTHOR) == 0)
&& propval
@@ -485,42 +533,31 @@ svn_client_revprop_set2(const char *prop
SVN_ERR(svn_client__get_revision_number(set_rev, NULL, ctx->wc_ctx, NULL,
ra_session, revision, pool));
- if (original_propval)
- {
- /* Ensure old value hasn't changed behind our back. */
- svn_string_t *current;
- SVN_ERR(svn_ra_rev_prop(ra_session, *set_rev, propname, ¤t, pool));
+ SVN_ERR(svn_ra_has_capability(ra_session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS, pool));
+ if (be_atomic)
+ {
+ /* Convert ORIGINAL_PROPVAL to an OLD_VALUE_P. */
+ const svn_string_t *const *old_value_p;
+ const svn_string_t *unset = NULL;
+
+ if (original_propval == NULL)
+ old_value_p = NULL;
+ else if (original_propval->data == NULL)
+ old_value_p = &unset;
+ else
+ old_value_p = &original_propval;
- if (original_propval->data && (! current))
- {
- return svn_error_createf(
- SVN_ERR_RA_OUT_OF_DATE, NULL,
- _("revprop '%s' in r%ld is unexpectedly absent "
- "in repository (maybe someone else deleted it?)"),
- propname, *set_rev);
- }
- else if (original_propval->data
- && (! svn_string_compare(original_propval, current)))
- {
- return svn_error_createf(
- SVN_ERR_RA_OUT_OF_DATE, NULL,
- _("revprop '%s' in r%ld has unexpected value "
- "in repository (maybe someone else changed it?)"),
- propname, *set_rev);
- }
- else if ((! original_propval->data) && current)
- {
- return svn_error_createf(
- SVN_ERR_RA_OUT_OF_DATE, NULL,
- _("revprop '%s' in r%ld is unexpectedly present "
- "in repository (maybe someone else set it?)"),
- propname, *set_rev);
- }
+ /* The actual RA call. */
+ SVN_ERR(svn_ra_change_rev_prop2(ra_session, *set_rev, propname,
+ old_value_p, propval, pool));
+ }
+ else
+ {
+ /* The actual RA call. */
+ SVN_ERR(check_and_set_revprop(set_rev, ra_session, propname,
+ original_propval, propval, pool));
}
-
- /* The actual RA call. */
- SVN_ERR(svn_ra_change_rev_prop(ra_session, *set_rev, propname, propval,
- pool));
if (ctx->notify_func2)
{
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c Sat Dec 11 00:15:55 2010
@@ -125,15 +125,91 @@ validator_func(void *baton,
return SVN_NO_ERROR;
}
+
+/* Examing the array of svn_wc_external_item2_t's EXT_DESC (parsed
+ from the svn:externals property set on LOCAL_ABSPATH) and determine
+ if the external working copies described by such should be
+ relocated as a side-effect of the relocation of their parent
+ working copy (from OLD_PARENT_REPOS_ROOT_URL to
+ NEW_PARENT_REPOS_ROOT_URL). If so, attempt said relocation. */
+static svn_error_t *
+relocate_externals(const char *local_abspath,
+ apr_array_header_t *ext_desc,
+ const char *old_parent_repos_root_url,
+ const char *new_parent_repos_root_url,
+ 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);
+
+ for (i = 0; i < ext_desc->nelts; i++)
+ {
+ svn_wc_external_item2_t *ext_item =
+ APR_ARRAY_IDX(ext_desc, i, svn_wc_external_item2_t *);
+ const char *target_repos_root_url;
+ const char *target_abspath;
+
+ svn_pool_clear(iterpool);
+
+ /* If this external isn't pulled in via a relative URL, ignore
+ it. There's no sense in relocating a working copy only to
+ have the next 'svn update' try to point it back to another
+ location. */
+ if (! ((strncmp("../", ext_item->url, 3) == 0) ||
+ (strncmp("^/", ext_item->url, 2) == 0)))
+ continue;
+
+ /* If the external working copy's not-yet-relocated repos root
+ URL matches the primary working copy's pre-relocated
+ repository root URL, try to relocate that external, too.
+ You might wonder why this check is needed, given that we're
+ already limiting ourselves to externals pulled via URLs
+ relative to their primary working copy. Well, it's because
+ you can use "../" to "crawl up" above one repository's URL
+ space and down into another one. */
+ SVN_ERR(svn_dirent_get_absolute(&target_abspath,
+ svn_dirent_join(local_abspath,
+ ext_item->target_dir,
+ iterpool),
+ iterpool));
+ SVN_ERR(svn_client_root_url_from_path(&target_repos_root_url,
+ target_abspath, ctx, iterpool));
+
+ if (strcmp(target_repos_root_url, old_parent_repos_root_url) == 0)
+ SVN_ERR(svn_client_relocate2(target_abspath,
+ old_parent_repos_root_url,
+ new_parent_repos_root_url,
+ TRUE, ctx, iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client_relocate2(const char *wcroot_dir,
- const char *from,
- const char *to,
+ const char *from_prefix,
+ const char *to_prefix,
+ svn_boolean_t ignore_externals,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
struct validator_baton_t vb;
const char *local_abspath;
+ apr_hash_t *externals_hash = NULL;
+ apr_hash_index_t *hi;
+ apr_pool_t *iterpool = NULL;
+ const char *old_repos_root_url, *new_repos_root_url;
/* Populate our validator callback baton, and call the relocate code. */
vb.ctx = ctx;
@@ -141,9 +217,61 @@ svn_client_relocate2(const char *wcroot_
vb.url_uuids = apr_array_make(pool, 1, sizeof(struct url_uuid_t));
vb.pool = pool;
+ if (svn_path_is_url(wcroot_dir))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a local path"),
+ wcroot_dir);
+
SVN_ERR(svn_dirent_get_absolute(&local_abspath, wcroot_dir, pool));
- SVN_ERR(svn_wc_relocate4(ctx->wc_ctx, local_abspath, from, to,
+
+ /* If we're ignoring externals, just relocate and get outta here. */
+ if (ignore_externals)
+ {
+ return svn_error_return(svn_wc_relocate4(ctx->wc_ctx, local_abspath,
+ from_prefix, to_prefix,
+ validator_func, &vb, pool));
+ }
+
+ /* Fetch our current root URL. */
+ SVN_ERR(svn_client_root_url_from_path(&old_repos_root_url, local_abspath,
+ ctx, 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));
+
+
+ /* Relocate externals, too (if any). */
+ SVN_ERR(svn_client__crawl_for_externals(&externals_hash, local_abspath,
+ svn_depth_infinity, ctx, pool, pool));
+ if (! apr_hash_count(externals_hash))
+ return SVN_NO_ERROR;
+
+ iterpool = svn_pool_create(pool);
+
+ for (hi = apr_hash_first(pool, externals_hash);
+ hi != NULL;
+ hi = apr_hash_next(hi))
+ {
+ const char *this_abspath = svn__apr_hash_index_key(hi);
+ const svn_string_t *pval = svn__apr_hash_index_val(hi);
+ apr_array_header_t *ext_desc;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_wc_parse_externals_description3(&ext_desc, this_abspath,
+ pval->data, FALSE,
+ iterpool));
+ if (ext_desc->nelts)
+ SVN_ERR(relocate_externals(this_abspath, ext_desc, old_repos_root_url,
+ new_repos_root_url, ctx, iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
+
return SVN_NO_ERROR;
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c Sat Dec 11 00:15:55 2010
@@ -521,7 +521,7 @@ diff_deleted_dir(const char *dir,
mimetype1, mimetype2,
b->pristine_props,
b->edit_baton->diff_cmd_baton,
- pool));
+ iterpool));
}
if (dirent->kind == svn_node_dir)
@@ -1060,7 +1060,8 @@ close_directory(void *dir_baton,
return SVN_NO_ERROR;
if (eb->dry_run)
- svn_hash__clear(svn_client__dry_run_deletions(eb->diff_cmd_baton), pool);
+ SVN_ERR(svn_hash__clear(svn_client__dry_run_deletions(eb->diff_cmd_baton),
+ pool));
err = get_dir_abspath(&local_dir_abspath, eb->wc_ctx, b->wcpath,
FALSE, b->pool);
@@ -1244,7 +1245,7 @@ absent_directory(const char *path,
svn_wc_notify_t *notify
= svn_wc_create_notify(svn_dirent_join(pb->wcpath,
svn_relpath_basename(path,
- pool),
+ NULL),
pool),
svn_wc_notify_skip, pool);
notify->kind = svn_node_dir;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c Sat Dec 11 00:15:55 2010
@@ -196,7 +196,7 @@ diff_deleted_dir(const char *dir,
&kind,
iterpool));
- sum = apr_pcalloc(pool, sizeof(*sum));
+ sum = apr_pcalloc(iterpool, sizeof(*sum));
sum->summarize_kind = svn_client_diff_summarize_kind_deleted;
sum->path = path;
sum->node_kind = kind;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/resolved.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/resolved.c Sat Dec 11 00:15:55 2010
@@ -36,6 +36,7 @@
#include "client.h"
#include "private/svn_wc_private.h"
+#include "svn_private_config.h"
/*** Code. ***/
@@ -48,6 +49,10 @@ svn_client_resolve(const char *path,
{
const char *local_abspath;
+ if (svn_path_is_url(path))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a local path"), path);
+
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
SVN_ERR(svn_wc_resolved_conflict5(ctx->wc_ctx, local_abspath,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c Sat Dec 11 00:15:55 2010
@@ -27,6 +27,7 @@
/*** Includes. ***/
+#include "svn_path.h"
#include "svn_wc.h"
#include "svn_client.h"
#include "svn_dirent_uri.h"
@@ -37,6 +38,7 @@
#include "client.h"
#include "private/svn_wc_private.h"
+#include "svn_private_config.h"
/*** Code. ***/
@@ -121,6 +123,17 @@ svn_client_revert2(const apr_array_heade
svn_boolean_t use_commit_times;
struct revert_with_write_lock_baton baton;
+ /* Don't even attempt to modify the working copy if any of the
+ * targets look like URLs. URLs are invalid input. */
+ for (i = 0; i < paths->nelts; i++)
+ {
+ const char *path = APR_ARRAY_IDX(paths, i, const char *);
+
+ if (svn_path_is_url(path))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a local path"), path);
+ }
+
cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING) : NULL;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c Sat Dec 11 00:15:55 2010
@@ -32,6 +32,7 @@
#include "svn_pools.h"
#include "client.h"
+#include "svn_path.h"
#include "svn_dirent_uri.h"
#include "svn_delta.h"
#include "svn_client.h"
@@ -306,7 +307,11 @@ svn_client_status5(svn_revnum_t *result_
apr_hash_t *ignored_props;
svn_error_t *err;
apr_hash_t *changelist_hash = NULL;
- struct svn_cl__externals_store externals_store = { NULL };
+ struct svn_client__external_func_baton_t externals_store = { NULL };
+
+ if (svn_path_is_url(path))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a local path"), path);
if (changelists && changelists->nelts)
SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelists, pool));
@@ -408,7 +413,7 @@ svn_client_status5(svn_revnum_t *result_
if (!ignore_externals)
{
- externals_store.pool = pool;
+ externals_store.result_pool = pool;
externals_store.externals_new = apr_hash_make(pool);
}
@@ -444,10 +449,10 @@ svn_client_status5(svn_revnum_t *result_
dir_abspath, target_basename,
depth, get_all,
no_ignore, ignores, tweak_status, &sb,
- ignore_externals ? NULL
- : svn_cl__store_externals,
- ignore_externals ? NULL
- : &externals_store,
+ ignore_externals
+ ? NULL
+ : svn_client__external_info_gatherer,
+ ignore_externals ? NULL : &externals_store,
ctx->cancel_func, ctx->cancel_baton,
pool, pool));
@@ -568,10 +573,10 @@ svn_client_status5(svn_revnum_t *result_
err = svn_wc_walk_status(ctx->wc_ctx, target_abspath,
depth, get_all, no_ignore, ignores,
tweak_status, &sb,
- ignore_externals ? NULL
- : svn_cl__store_externals,
- ignore_externals ? NULL
- : &externals_store,
+ ignore_externals
+ ? NULL
+ : svn_client__external_info_gatherer,
+ ignore_externals ? NULL : &externals_store,
ctx->cancel_func, ctx->cancel_baton,
pool);
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c Sat Dec 11 00:15:55 2010
@@ -329,6 +329,11 @@ svn_client_switch2(svn_revnum_t *result_
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
+ if (svn_path_is_url(path))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a local path"),
+ path);
+
return svn_client__switch_internal(result_rev, path, switch_url,
peg_revision, revision, depth,
depth_is_sticky, NULL, ignore_externals,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c Sat Dec 11 00:15:55 2010
@@ -44,7 +44,18 @@
/*** Code. ***/
-
+/* This is a helper for svn_client__update_internal(), which see for
+ an explanation of most of these parameters. Some stuff that's
+ unique is as follows:
+
+ ANCHOR_ABSPATH is the local absolute path of the update anchor.
+ 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
+ CTX), transmit the final update summary upon successful
+ completion of the update.
+*/
static svn_error_t *
update_internal(svn_revnum_t *result_rev,
const char *local_abspath,
@@ -56,6 +67,7 @@ update_internal(svn_revnum_t *result_rev
svn_boolean_t allow_unver_obstructions,
svn_boolean_t *timestamp_sleep,
svn_boolean_t innerupdate,
+ svn_boolean_t notify_summary,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -144,6 +156,20 @@ update_internal(svn_revnum_t *result_rev
? svn_cstring_split(preserved_exts_str, "\n\r\t\v ", FALSE, pool)
: NULL;
+ /* Let everyone know we're starting a real update (unless we're
+ asked not to). */
+ if (ctx->notify_func2 && notify_summary)
+ {
+ svn_wc_notify_t *notify
+ = svn_wc_create_notify(local_abspath, svn_wc_notify_update_started,
+ pool);
+ notify->kind = svn_node_none;
+ notify->content_state = notify->prop_state
+ = svn_wc_notify_state_inapplicable;
+ notify->lock_state = svn_wc_notify_lock_state_inapplicable;
+ (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+ }
+
/* Open an RA session for the URL */
SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
anchor_url,
@@ -154,8 +180,8 @@ update_internal(svn_revnum_t *result_rev
relocate our working copy first. */
if (corrected_url)
{
- SVN_ERR(svn_client_relocate(anchor_abspath, anchor_url, corrected_url,
- TRUE, ctx, pool));
+ SVN_ERR(svn_client_relocate2(anchor_abspath, anchor_url, corrected_url,
+ TRUE, ctx, pool));
anchor_url = corrected_url;
}
@@ -235,8 +261,8 @@ update_internal(svn_revnum_t *result_rev
if (sleep_here)
svn_io_sleep_for_timestamps(local_abspath, pool);
- /* Let everyone know we're finished here. */
- if (ctx->notify_func2)
+ /* Let everyone know we're finished here (unless we're asked not to). */
+ if (ctx->notify_func2 && notify_summary)
{
svn_wc_notify_t *notify
= svn_wc_create_notify(local_abspath, svn_wc_notify_update_completed,
@@ -266,44 +292,99 @@ svn_client__update_internal(svn_revnum_t
svn_boolean_t allow_unver_obstructions,
svn_boolean_t *timestamp_sleep,
svn_boolean_t innerupdate,
+ svn_boolean_t make_parents,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
- const char *anchor_abspath;
+ const char *anchor_abspath, *lockroot_abspath;
svn_error_t *err;
+ svn_opt_revision_t peg_revision = *((svn_opt_revision_t *)revision);
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+ SVN_ERR_ASSERT(! (innerupdate && make_parents));
- if (!innerupdate)
- SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath,
- ctx->wc_ctx, local_abspath, TRUE,
- pool, pool));
+ if (make_parents)
+ {
+ int i;
+ const char *parent_abspath = local_abspath;
+ apr_array_header_t *missing_parents =
+ apr_array_make(pool, 4, sizeof(const char *));
+
+ while (1)
+ {
+ /* Try to lock. If we can't lock because our target (or its
+ parent) isn't a working copy, we'll try to walk up the
+ tree to find a working copy, remembering this path's
+ parent as one we need to flesh out. */
+ err = svn_wc__acquire_write_lock(&lockroot_abspath, ctx->wc_ctx,
+ parent_abspath, !innerupdate,
+ pool, pool);
+ if (!err)
+ break;
+ if ((err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+ || svn_dirent_is_root(parent_abspath, strlen(parent_abspath)))
+ return err;
+ svn_error_clear(err);
+
+ /* Remember the parent of our update target as a missing
+ parent. */
+ parent_abspath = svn_dirent_dirname(parent_abspath, pool);
+ APR_ARRAY_PUSH(missing_parents, const char *) = parent_abspath;
+ }
+
+ /* Run 'svn up --depth=empty' (effectively) on the missing
+ parents, if any. */
+ anchor_abspath = lockroot_abspath;
+ for (i = missing_parents->nelts - 1; i >= 0; i--)
+ {
+ const char *missing_parent =
+ APR_ARRAY_IDX(missing_parents, i, const char *);
+ err = update_internal(result_rev, missing_parent, anchor_abspath,
+ &peg_revision, svn_depth_empty, FALSE,
+ ignore_externals, allow_unver_obstructions,
+ timestamp_sleep, innerupdate, FALSE,
+ ctx, pool);
+ if (err)
+ goto cleanup;
+ anchor_abspath = missing_parent;
+
+ /* If we successfully updated a missing parent, let's re-use
+ the returned revision number for future updates for the
+ sake of consistency. */
+ peg_revision.kind = svn_opt_revision_number;
+ peg_revision.value.number = *result_rev;
+ }
+ }
else
- SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath,
- ctx->wc_ctx, local_abspath, FALSE,
- pool, pool));
+ {
+ SVN_ERR(svn_wc__acquire_write_lock(&lockroot_abspath, ctx->wc_ctx,
+ local_abspath, !innerupdate,
+ pool, pool));
+ anchor_abspath = lockroot_abspath;
+ }
err = update_internal(result_rev, local_abspath, anchor_abspath,
- revision, depth, depth_is_sticky,
- ignore_externals, allow_unver_obstructions,
- timestamp_sleep, innerupdate, ctx, pool);
-
+ &peg_revision, depth, depth_is_sticky,
+ ignore_externals, allow_unver_obstructions,
+ timestamp_sleep, innerupdate, TRUE, ctx, pool);
+ cleanup:
err = svn_error_compose_create(
err,
- svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool));
+ svn_wc__release_write_lock(ctx->wc_ctx, lockroot_abspath, pool));
return svn_error_return(err);
}
svn_error_t *
-svn_client_update3(apr_array_header_t **result_revs,
+svn_client_update4(apr_array_header_t **result_revs,
const apr_array_header_t *paths,
const svn_opt_revision_t *revision,
svn_depth_t depth,
svn_boolean_t depth_is_sticky,
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
+ svn_boolean_t make_parents,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -316,10 +397,19 @@ svn_client_update3(apr_array_header_t **
for (i = 0; i < paths->nelts; ++i)
{
+ path = APR_ARRAY_IDX(paths, i, const char *);
+
+ if (svn_path_is_url(path))
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("'%s' is not a local path"), path);
+ }
+
+ for (i = 0; i < paths->nelts; ++i)
+ {
svn_boolean_t sleep;
- svn_boolean_t skipped = FALSE;
svn_error_t *err = SVN_NO_ERROR;
svn_revnum_t result_rev;
+ const char *local_abspath;
path = APR_ARRAY_IDX(paths, i, const char *);
svn_pool_clear(subpool);
@@ -327,56 +417,30 @@ svn_client_update3(apr_array_header_t **
if (ctx->cancel_func && (err = ctx->cancel_func(ctx->cancel_baton)))
break;
- if (svn_path_is_url(path))
- {
- skipped = TRUE;
- }
- else
- {
- const char *local_abspath;
-
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
- err = svn_client__update_internal(&result_rev, local_abspath,
- revision, depth, depth_is_sticky,
- ignore_externals,
- allow_unver_obstructions,
- &sleep, FALSE, ctx, subpool);
-
- if (err && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
- {
- return svn_error_return(err);
- }
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
+ err = svn_client__update_internal(&result_rev, local_abspath,
+ revision, depth, depth_is_sticky,
+ ignore_externals,
+ allow_unver_obstructions,
+ &sleep, FALSE, make_parents,
+ ctx, subpool);
- if (err)
- {
- /* SVN_ERR_WC_NOT_WORKING_COPY: it's not versioned */
- svn_error_clear(err);
- skipped = TRUE;
- }
+ if (err && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+ {
+ return svn_error_return(err);
}
- if (skipped)
+ if (err)
{
+ /* SVN_ERR_WC_NOT_WORKING_COPY: it's not versioned */
+ svn_error_clear(err);
result_rev = SVN_INVALID_REVNUM;
if (ctx->notify_func2)
{
svn_wc_notify_t *notify;
-
- if (svn_path_is_url(path))
- {
- /* For some historic reason this user error is supported,
- and must provide correct notifications. */
- notify = svn_wc_create_notify_url(path,
- svn_wc_notify_skip,
- subpool);
- }
- else
- {
- notify = svn_wc_create_notify(path,
- svn_wc_notify_skip,
- subpool);
- }
-
+ notify = svn_wc_create_notify(path,
+ svn_wc_notify_skip,
+ subpool);
(*ctx->notify_func2)(ctx->notify_baton2, notify, subpool);
}
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/util.c Sat Dec 11 00:15:55 2010
@@ -34,6 +34,7 @@
#include "svn_wc.h"
#include "svn_client.h"
+#include "private/svn_client_private.h"
#include "private/svn_wc_private.h"
#include "client.h"
@@ -218,7 +219,9 @@ svn_client__path_relative_to_root(const
}
rel_url = svn_path_uri_decode(rel_url, result_pool);
*rel_path = include_leading_slash
- ? apr_pstrcat(result_pool, "/", rel_url, NULL) : rel_url;
+ ? apr_pstrcat(result_pool, "/", rel_url,
+ (char *)NULL)
+ : rel_url;
}
return SVN_NO_ERROR;
@@ -318,3 +321,25 @@ svn_cl__rev_default_to_peg(const svn_opt
return peg_revision;
return revision;
}
+
+svn_error_t *
+svn_client__assert_homogeneous_target_type(const apr_array_header_t *targets)
+{
+ svn_boolean_t wc_present = FALSE, url_present = FALSE;
+ int i;
+
+ for (i = 0; i < targets->nelts; ++i)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+ if (! svn_path_is_url(target))
+ wc_present = TRUE;
+ else
+ url_present = TRUE;
+ if (url_present && wc_present)
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("Cannot mix repository and working copy "
+ "targets"));
+ }
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/path_driver.c Sat Dec 11 00:15:55 2010
@@ -194,7 +194,9 @@ svn_delta_path_driver(const svn_delta_ed
current one. For the first iteration, this is just the
empty string. ***/
if (i > 0)
- common = svn_relpath_get_longest_ancestor(last_path, path, iterpool);
+ common = (last_path[0] == '/')
+ ? svn_fspath__get_longest_ancestor(last_path, path, iterpool)
+ : svn_relpath_get_longest_ancestor(last_path, path, iterpool);
common_len = strlen(common);
/*** Step B - Close any directories between the last path and
@@ -215,7 +217,7 @@ svn_delta_path_driver(const svn_delta_ed
/*** Step C - Open any directories between the common ancestor
and the parent of the current path. ***/
if (*path == '/')
- svn_uri_split(&pdir, &bname, path, iterpool);
+ svn_fspath__split(&pdir, &bname, path, iterpool);
else
svn_relpath_split(&pdir, &bname, path, iterpool);
if (strlen(pdir) > common_len)
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c Sat Dec 11 00:15:55 2010
@@ -352,10 +352,13 @@ struct decode_baton
};
-/* Decode an svndiff-encoded integer into VAL and return a pointer to
+/* Decode an svndiff-encoded integer into *VAL and return a pointer to
the byte after the integer. The bytes to be decoded live in the
- range [P..END-1]. See the comment for encode_int earlier in this
- file for more detail on the encoding format. */
+ range [P..END-1]. If these bytes do not contain a whole encoded
+ integer, return NULL; in this case *VAL is undefined.
+
+ See the comment for encode_int() earlier in this file for more detail on
+ the encoding format. */
static const unsigned char *
decode_file_offset(svn_filesize_t *val,
const unsigned char *p,
@@ -381,7 +384,6 @@ decode_file_offset(svn_filesize_t *val,
}
}
- *val = temp;
return NULL;
}
@@ -409,7 +411,6 @@ decode_size(apr_size_t *val,
}
}
- *val = temp;
return NULL;
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c Sat Dec 11 00:15:55 2010
@@ -67,21 +67,26 @@ typedef struct svn_diff__file_token_t
typedef struct svn_diff__file_baton_t
{
const svn_diff_file_options_t *options;
- const char *path[4];
- apr_file_t *file[4];
- apr_off_t size[4];
+ struct file_info {
+ const char *path; /* path to this file, absolute or relative to CWD */
- int chunk[4];
- char *buffer[4];
- char *curp[4];
- char *endp[4];
+ /* All the following fields are active while this datasource is open */
+ apr_file_t *file; /* handle of this file */
+ apr_off_t size; /* total raw size in bytes of this file */
+
+ /* The current chunk: CHUNK_SIZE bytes except for the last chunk. */
+ int chunk; /* the current chunk number, zero-based */
+ char *buffer; /* a buffer containing the current chunk */
+ char *curp; /* current position in the current chunk */
+ char *endp; /* next memory address after the current chunk */
+
+ svn_diff__normalize_state_t normalize_state;
+ } files[4];
/* List of free tokens that may be reused. */
svn_diff__file_token_t *tokens;
- svn_diff__normalize_state_t normalize_state[4];
-
apr_pool_t *pool;
} svn_diff__file_baton_t;
@@ -198,26 +203,30 @@ map_or_read_file(apr_file_t **file,
}
-/* Implements svn_diff_fns_t::datasource_open */
+/* Let FILE stand for the file_info struct element of BATON->files that is
+ * indexed by DATASOURCE. BATON's type is (svn_diff__file_baton_t *).
+ *
+ * Open the file at FILE.path; initialize FILE.file, FILE.size, FILE.buffer,
+ * FILE.curp and FILE.endp; allocate a buffer and read the first chunk.
+ *
+ * Implements svn_diff_fns_t::datasource_open. */
static svn_error_t *
datasource_open(void *baton, svn_diff_datasource_e datasource)
{
svn_diff__file_baton_t *file_baton = baton;
- int idx;
+ struct file_info *file = &file_baton->files[datasource_to_index(datasource)];
apr_finfo_t finfo;
apr_off_t length;
char *curp;
char *endp;
- idx = datasource_to_index(datasource);
-
- SVN_ERR(svn_io_file_open(&file_baton->file[idx], file_baton->path[idx],
+ SVN_ERR(svn_io_file_open(&file->file, file->path,
APR_READ, APR_OS_DEFAULT, file_baton->pool));
SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE,
- file_baton->file[idx], file_baton->pool));
+ file->file, file_baton->pool));
- file_baton->size[idx] = finfo.size;
+ file->size = finfo.size;
length = finfo.size > CHUNK_SIZE ? CHUNK_SIZE : finfo.size;
if (length == 0)
@@ -226,10 +235,10 @@ datasource_open(void *baton, svn_diff_da
endp = curp = apr_palloc(file_baton->pool, (apr_size_t) length);
endp += length;
- file_baton->buffer[idx] = file_baton->curp[idx] = curp;
- file_baton->endp[idx] = endp;
+ file->buffer = file->curp = curp;
+ file->endp = endp;
- return read_chunk(file_baton->file[idx], file_baton->path[idx],
+ return read_chunk(file->file, file->path,
curp, length, 0, file_baton->pool);
}
@@ -252,7 +261,7 @@ datasource_get_next_token(apr_uint32_t *
{
svn_diff__file_baton_t *file_baton = baton;
svn_diff__file_token_t *file_token;
- int idx;
+ struct file_info *file = &file_baton->files[datasource_to_index(datasource)];
char *endp;
char *curp;
char *eol;
@@ -264,15 +273,13 @@ datasource_get_next_token(apr_uint32_t *
*token = NULL;
- idx = datasource_to_index(datasource);
-
- curp = file_baton->curp[idx];
- endp = file_baton->endp[idx];
+ curp = file->curp;
+ endp = file->endp;
- last_chunk = offset_to_chunk(file_baton->size[idx]);
+ last_chunk = offset_to_chunk(file->size);
if (curp == endp
- && last_chunk == file_baton->chunk[idx])
+ && last_chunk == file->chunk)
{
return SVN_NO_ERROR;
}
@@ -289,8 +296,8 @@ datasource_get_next_token(apr_uint32_t *
}
file_token->datasource = datasource;
- file_token->offset = chunk_to_offset(file_baton->chunk[idx])
- + (curp - file_baton->buffer[idx]);
+ file_token->offset = chunk_to_offset(file->chunk)
+ + (curp - file->buffer);
file_token->raw_length = 0;
file_token->length = 0;
@@ -311,7 +318,7 @@ datasource_get_next_token(apr_uint32_t *
}
}
- if (file_baton->chunk[idx] == last_chunk)
+ if (file->chunk == last_chunk)
{
eol = endp;
break;
@@ -320,21 +327,21 @@ datasource_get_next_token(apr_uint32_t *
length = endp - curp;
file_token->raw_length += length;
svn_diff__normalize_buffer(&curp, &length,
- &file_baton->normalize_state[idx],
+ &file->normalize_state,
curp, file_baton->options);
file_token->length += length;
h = svn_diff__adler32(h, curp, length);
- curp = endp = file_baton->buffer[idx];
- file_baton->chunk[idx]++;
- length = file_baton->chunk[idx] == last_chunk ?
- offset_in_chunk(file_baton->size[idx]) : CHUNK_SIZE;
+ curp = endp = file->buffer;
+ file->chunk++;
+ length = file->chunk == last_chunk ?
+ offset_in_chunk(file->size) : CHUNK_SIZE;
endp += length;
- file_baton->endp[idx] = endp;
+ file->endp = endp;
- SVN_ERR(read_chunk(file_baton->file[idx], file_baton->path[idx],
+ SVN_ERR(read_chunk(file->file, file->path,
curp, length,
- chunk_to_offset(file_baton->chunk[idx]),
+ chunk_to_offset(file->chunk),
file_baton->pool));
/* If the last chunk ended in a CR, we're done. */
@@ -349,7 +356,7 @@ datasource_get_next_token(apr_uint32_t *
length = eol - curp;
file_token->raw_length += length;
- file_baton->curp[idx] = eol;
+ file->curp = eol;
/* If the file length is exactly a multiple of CHUNK_SIZE, we will end up
* with a spurious empty token. Avoid returning it.
@@ -360,7 +367,7 @@ datasource_get_next_token(apr_uint32_t *
{
char *c = curp;
svn_diff__normalize_buffer(&c, &length,
- &file_baton->normalize_state[idx],
+ &file->normalize_state,
curp, file_baton->options);
file_token->norm_offset = file_token->offset;
@@ -388,13 +395,12 @@ token_compare(void *baton, void *token1,
char buffer[2][COMPARE_CHUNK_SIZE];
char *bufp[2];
apr_off_t offset[2];
- int idx[2];
+ struct file_info *file[2];
apr_off_t length[2];
apr_off_t total_length;
/* How much is left to read of each token from the file. */
apr_off_t raw_length[2];
int i;
- int chunk[2];
svn_diff__normalize_state_t state[2];
file_token[0] = token1;
@@ -420,17 +426,18 @@ token_compare(void *baton, void *token1,
for (i = 0; i < 2; ++i)
{
- idx[i] = datasource_to_index(file_token[i]->datasource);
+ int idx = datasource_to_index(file_token[i]->datasource);
+
+ file[i] = &file_baton->files[idx];
offset[i] = file_token[i]->norm_offset;
- chunk[i] = file_baton->chunk[idx[i]];
state[i] = svn_diff__normalize_state_normal;
- if (offset_to_chunk(offset[i]) == chunk[i])
+ if (offset_to_chunk(offset[i]) == file[i]->chunk)
{
/* If the start of the token is in memory, the entire token is
* in memory.
*/
- bufp[i] = file_baton->buffer[idx[i]];
+ bufp[i] = file[i]->buffer;
bufp[i] += offset_in_chunk(offset[i]);
length[i] = total_length;
@@ -458,15 +465,15 @@ token_compare(void *baton, void *token1,
NULL,
_("The file '%s' changed unexpectedly"
" during diff"),
- file_baton->path[idx[i]]);
+ file[i]->path);
/* Read a chunk from disk into a buffer */
bufp[i] = buffer[i];
length[i] = raw_length[i] > COMPARE_CHUNK_SIZE ?
COMPARE_CHUNK_SIZE : raw_length[i];
- SVN_ERR(read_chunk(file_baton->file[idx[i]],
- file_baton->path[idx[i]],
+ SVN_ERR(read_chunk(file[i]->file,
+ file[i]->path,
bufp[i], length[i], offset[i],
file_baton->pool));
offset[i] += length[i];
@@ -555,12 +562,42 @@ svn_diff_file_options_create(apr_pool_t
return apr_pcalloc(pool, sizeof(svn_diff_file_options_t));
}
+/* A baton for use with opt_parsing_error_func(). */
+struct opt_parsing_error_baton_t
+{
+ svn_error_t *err;
+ apr_pool_t *pool;
+};
+
+/* Store an error message from apr_getopt_long(). Set BATON->err to a new
+ * error with a message generated from FMT and the remaining arguments.
+ * Implements apr_getopt_err_fn_t. */
+static void
+opt_parsing_error_func(void *baton,
+ const char *fmt, ...)
+{
+ struct opt_parsing_error_baton_t *b = baton;
+ const char *message;
+ va_list ap;
+
+ va_start(ap, fmt);
+ message = apr_pvsprintf(b->pool, fmt, ap);
+ va_end(ap);
+
+ /* Skip leading ": " (if present, which it always is in known cases). */
+ if (strncmp(message, ": ", 2) == 0)
+ message += 2;
+
+ b->err = svn_error_create(SVN_ERR_INVALID_DIFF_OPTION, NULL, message);
+}
+
svn_error_t *
svn_diff_file_options_parse(svn_diff_file_options_t *options,
const apr_array_header_t *args,
apr_pool_t *pool)
{
apr_getopt_t *os;
+ struct opt_parsing_error_baton_t opt_parsing_error_baton = { NULL, pool };
/* Make room for each option (starting at index 1) plus trailing NULL. */
const char **argv = apr_palloc(pool, sizeof(char*) * (args->nelts + 2));
@@ -569,8 +606,12 @@ svn_diff_file_options_parse(svn_diff_fil
argv[args->nelts + 1] = NULL;
apr_getopt_init(&os, pool, args->nelts + 1, argv);
- /* No printing of error messages, please! */
- os->errfn = NULL;
+
+ /* Capture any error message from apr_getopt_long(). This will typically
+ * say which option is wrong, which we would not otherwise know. */
+ os->errfn = opt_parsing_error_func;
+ os->errarg = &opt_parsing_error_baton;
+
while (1)
{
const char *opt_arg;
@@ -580,7 +621,13 @@ svn_diff_file_options_parse(svn_diff_fil
if (APR_STATUS_IS_EOF(err))
break;
if (err)
- return svn_error_wrap_apr(err, _("Error parsing diff options"));
+ /* Wrap apr_getopt_long()'s error message. Its doc string implies
+ * it always will produce one, but never mind if it doesn't. Avoid
+ * using the message associated with the return code ERR, because
+ * it refers to the "command line" which may be misleading here. */
+ return svn_error_create(SVN_ERR_INVALID_DIFF_OPTION,
+ opt_parsing_error_baton.err,
+ _("Error in options to internal diff"));
switch (opt_id)
{
@@ -623,8 +670,8 @@ svn_diff_file_diff_2(svn_diff_t **diff,
memset(&baton, 0, sizeof(baton));
baton.options = options;
- baton.path[0] = original;
- baton.path[1] = modified;
+ baton.files[0].path = original;
+ baton.files[1].path = modified;
baton.pool = svn_pool_create(pool);
SVN_ERR(svn_diff_diff(diff, &baton, &svn_diff__file_vtable, pool));
@@ -645,9 +692,9 @@ svn_diff_file_diff3_2(svn_diff_t **diff,
memset(&baton, 0, sizeof(baton));
baton.options = options;
- baton.path[0] = original;
- baton.path[1] = modified;
- baton.path[2] = latest;
+ baton.files[0].path = original;
+ baton.files[1].path = modified;
+ baton.files[2].path = latest;
baton.pool = svn_pool_create(pool);
SVN_ERR(svn_diff_diff3(diff, &baton, &svn_diff__file_vtable, pool));
@@ -669,10 +716,10 @@ svn_diff_file_diff4_2(svn_diff_t **diff,
memset(&baton, 0, sizeof(baton));
baton.options = options;
- baton.path[0] = original;
- baton.path[1] = modified;
- baton.path[2] = latest;
- baton.path[3] = ancestor;
+ baton.files[0].path = original;
+ baton.files[1].path = modified;
+ baton.files[2].path = latest;
+ baton.files[3].path = ancestor;
baton.pool = svn_pool_create(pool);
SVN_ERR(svn_diff_diff4(diff, &baton, &svn_diff__file_vtable, pool));
@@ -1130,11 +1177,11 @@ svn_diff_file_output_unified3(svn_stream
apr_pool_t *pool)
{
svn_diff__file_output_baton_t baton;
- int i;
if (svn_diff_contains_diffs(diff))
{
const char **c;
+ int i;
memset(&baton, 0, sizeof(baton));
baton.output_stream = output_stream;
@@ -1161,42 +1208,44 @@ svn_diff_file_output_unified3(svn_stream
SVN_ERR(svn_utf_cstring_from_utf8_ex2(&baton.insert_str, "+",
header_encoding, pool));
- if (relative_to_dir)
- {
- /* Possibly adjust the "original" and "modified" paths shown in
- the output (see issue #2723). */
- const char *child_path;
-
- if (! original_header)
- {
- child_path = svn_dirent_is_child(relative_to_dir,
- original_path, pool);
- if (child_path)
- original_path = child_path;
- else
- return svn_error_createf(
- SVN_ERR_BAD_RELATIVE_PATH, NULL,
- _("Path '%s' must be an immediate child of "
- "the directory '%s'"),
- svn_dirent_local_style(original_path, pool),
- svn_dirent_local_style(relative_to_dir, pool));
- }
-
- if (! modified_header)
- {
- child_path = svn_dirent_is_child(relative_to_dir,
- modified_path, pool);
- if (child_path)
- modified_path = child_path;
- else
- return svn_error_createf(
- SVN_ERR_BAD_RELATIVE_PATH, NULL,
- _("Path '%s' must be an immediate child of "
- "the directory '%s'"),
- svn_dirent_local_style(modified_path, pool),
- svn_dirent_local_style(relative_to_dir, pool));
+ if (relative_to_dir)
+ {
+ /* Possibly adjust the "original" and "modified" paths shown in
+ the output (see issue #2723). */
+ const char *child_path;
+
+ if (! original_header)
+ {
+ child_path = svn_dirent_is_child(relative_to_dir,
+ original_path, pool);
+ if (child_path)
+ original_path = child_path;
+ else
+ return svn_error_createf(
+ SVN_ERR_BAD_RELATIVE_PATH, NULL,
+ _("Path '%s' must be an immediate child of "
+ "the directory '%s'"),
+ svn_dirent_local_style(original_path, pool),
+ svn_dirent_local_style(relative_to_dir,
+ pool));
+ }
+
+ if (! modified_header)
+ {
+ child_path = svn_dirent_is_child(relative_to_dir,
+ modified_path, pool);
+ if (child_path)
+ modified_path = child_path;
+ else
+ return svn_error_createf(
+ SVN_ERR_BAD_RELATIVE_PATH, NULL,
+ _("Path '%s' must be an immediate child of "
+ "the directory '%s'"),
+ svn_dirent_local_style(modified_path, pool),
+ svn_dirent_local_style(relative_to_dir,
+ pool));
+ }
}
- }
for (i = 0; i < 2; i++)
{
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c Sat Dec 11 00:15:55 2010
@@ -28,6 +28,7 @@
#include "svn_error.h"
#include "svn_io.h"
#include "svn_pools.h"
+#include "svn_props.h"
#include "svn_string.h"
#include "svn_utf.h"
#include "svn_dirent_uri.h"
@@ -150,7 +151,7 @@ parse_range(svn_linenum_t *start, svn_li
{
char *comma;
- if (strlen(range) == 0)
+ if (*range == 0)
return FALSE;
comma = strstr(range, ",");
@@ -189,6 +190,7 @@ parse_hunk_header(const char *header, sv
const char *atat, apr_pool_t *pool)
{
const char *p;
+ const char *start;
svn_stringbuf_t *range;
p = header + strlen(atat);
@@ -201,16 +203,18 @@ parse_hunk_header(const char *header, sv
return FALSE;
/* OK, this may be worth allocating some memory for... */
range = svn_stringbuf_create_ensure(31, pool);
- p++;
+ start = ++p;
while (*p && *p != ' ')
{
- svn_stringbuf_appendbyte(range, *p);
p++;
}
+
if (*p != ' ')
/* No no no... */
return FALSE;
+ svn_stringbuf_appendbytes(range, start, p - start);
+
/* Try to parse the first range. */
if (! parse_range(&hunk->original_start, &hunk->original_length, range->data))
return FALSE;
@@ -222,16 +226,17 @@ parse_hunk_header(const char *header, sv
/* Eeek! */
return FALSE;
/* OK, this may be worth copying... */
- p++;
+ start = ++p;
while (*p && *p != ' ')
{
- svn_stringbuf_appendbyte(range, *p);
p++;
}
if (*p != ' ')
/* No no no... */
return FALSE;
+ svn_stringbuf_appendbytes(range, start, p - start);
+
/* Check for trailing @@ */
p++;
if (! starts_with(p, atat))
@@ -477,19 +482,24 @@ svn_diff_hunk_readline_diff_text(const s
return SVN_NO_ERROR;
}
-/* Parse PROP_NAME from HEADER as the part after the INDICATOR line. */
+/* Parse *PROP_NAME from HEADER as the part after the INDICATOR line.
+ * Allocate *PROP_NAME in RESULT_POOL.
+ * Set *PROP_NAME to NULL if no valid property name was found. */
static svn_error_t *
parse_prop_name(const char **prop_name, const char *header,
const char *indicator, apr_pool_t *result_pool)
{
- /* ### This can fail if the filename cannot be represented in the current
- * ### locale's encoding. */
SVN_ERR(svn_utf_cstring_to_utf8(prop_name,
header + strlen(indicator),
result_pool));
-
- /* ### Are we guarenteed that there are no trailing or leading
- * ### whitespaces in the name? */
+ if (**prop_name == '\0')
+ *prop_name = NULL;
+ else if (! svn_prop_name_is_valid(*prop_name))
+ {
+ svn_stringbuf_t *buf = svn_stringbuf_create(*prop_name, result_pool);
+ svn_stringbuf_strip_whitespace(buf);
+ *prop_name = (svn_prop_name_is_valid(buf->data) ? buf->data : NULL);
+ }
return SVN_NO_ERROR;
}
@@ -674,20 +684,23 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
else if (starts_with(line->data, "Added: "))
{
SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ",
- result_pool));
- *prop_operation = svn_diff_op_added;
+ result_pool));
+ if (*prop_name)
+ *prop_operation = svn_diff_op_added;
}
else if (starts_with(line->data, "Deleted: "))
{
SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ",
result_pool));
- *prop_operation = svn_diff_op_deleted;
+ if (*prop_name)
+ *prop_operation = svn_diff_op_deleted;
}
else if (starts_with(line->data, "Modified: "))
{
SVN_ERR(parse_prop_name(prop_name, line->data, "Modified: ",
result_pool));
- *prop_operation = svn_diff_op_modified;
+ if (*prop_name)
+ *prop_operation = svn_diff_op_modified;
}
else if (starts_with(line->data, minus)
|| starts_with(line->data, "diff --git "))
@@ -1027,7 +1040,7 @@ git_move_from(enum parse_state *new_stat
return SVN_NO_ERROR;
}
-/* Parse the 'rename to ' line fo a git extended unidiff. */
+/* Parse the 'rename to ' line of a git extended unidiff. */
static svn_error_t *
git_move_to(enum parse_state *new_state, const char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
@@ -1262,6 +1275,8 @@ svn_diff_parse_next_patch(svn_patch_t **
const char *prop_name;
svn_diff_operation_kind_t prop_operation;
+ last_prop_name = NULL;
+
/* Parse hunks. */
(*patch)->hunks = apr_array_make(result_pool, 10,
sizeof(svn_diff_hunk_t *));
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.c Sat Dec 11 00:15:55 2010
@@ -684,7 +684,15 @@ svn_fs_commit_txn(const char **conflict_
SVN_ERR(txn->vtable->commit(conflict_p, new_rev, txn, pool));
#ifdef PACK_AFTER_EVERY_COMMIT
- SVN_ERR(svn_fs_pack(fs_path, NULL, NULL, NULL, NULL, pool));
+ {
+ svn_error_t *err = svn_fs_pack(fs_path, NULL, NULL, NULL, NULL, pool);
+ if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
+ /* Pre-1.6 filesystem. */
+ svn_error_clear(err);
+ else if (err)
+ /* Real error. */
+ return svn_error_return(err);
+ }
#endif
return SVN_NO_ERROR;
@@ -991,6 +999,22 @@ svn_fs_closest_copy(svn_fs_root_t **root
}
svn_error_t *
+svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
+ svn_fs_root_t *root,
+ const apr_array_header_t *paths,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
+ svn_boolean_t include_descendants,
+ apr_pool_t *pool)
+{
+ return svn_error_return(root->vtable->get_mergeinfo(catalog, root, paths,
+ inherit,
+ validate_inherited_mergeinfo,
+ include_descendants,
+ pool));
+}
+
+svn_error_t *
svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
svn_fs_root_t *root,
const apr_array_header_t *paths,
@@ -998,10 +1022,24 @@ svn_fs_get_mergeinfo(svn_mergeinfo_catal
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
- return svn_error_return(root->vtable->get_mergeinfo(catalog, root, paths,
- inherit,
- include_descendants,
- pool));
+ return svn_error_return(svn_fs_get_mergeinfo2(catalog, root, paths,
+ inherit,
+ FALSE,
+ include_descendants,
+ pool));
+}
+
+svn_error_t *
+svn_fs_validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+ svn_fs_t *fs,
+ svn_mergeinfo_t mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_return(fs->vtable->validate_mergeinfo(validated_mergeinfo,
+ fs, mergeinfo,
+ result_pool,
+ scratch_pool));
}
svn_error_t *
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs/fs-loader.h Sat Dec 11 00:15:55 2010
@@ -197,6 +197,11 @@ typedef struct fs_vtable_t
svn_error_t *(*bdb_set_errcall)(svn_fs_t *fs,
void (*handler)(const char *errpfx,
char *msg));
+ svn_error_t *(*validate_mergeinfo)(svn_mergeinfo_t *validated_mergeinfo,
+ svn_fs_t *fs,
+ svn_mergeinfo_t mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
} fs_vtable_t;
@@ -331,6 +336,7 @@ typedef struct root_vtable_t
svn_fs_root_t *root,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool);
} root_vtable_t;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c Sat Dec 11 00:15:55 2010
@@ -250,7 +250,7 @@ svn_fs_bdb__locks_get(svn_fs_t *fs,
/* As long as the prefix of the returned KEY matches LOOKUP_PATH we
know it is either LOOKUP_PATH or a decendant thereof. */
if (strcmp(path, "/") != 0)
- lookup_path = apr_pstrcat(pool, path, "/", NULL);
+ lookup_path = apr_pstrcat(pool, path, "/", (char *)NULL);
while ((! db_err)
&& strncmp(lookup_path, key.data, strlen(lookup_path)) == 0)
{
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/dag.c Sat Dec 11 00:15:55 2010
@@ -481,7 +481,7 @@ make_entry(dag_node_t **child_p,
/* Create the new node's NODE-REVISION */
memset(&new_noderev, 0, sizeof(new_noderev));
new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
- new_noderev.created_path = svn_uri_join(parent_path, name, pool);
+ new_noderev.created_path = svn_fspath__join(parent_path, name, pool);
SVN_ERR(svn_fs_base__create_node
(&new_node_id, svn_fs_base__dag_get_fs(parent), &new_noderev,
svn_fs_base__id_copy_id(svn_fs_base__dag_get_id(parent)),
@@ -763,7 +763,7 @@ svn_fs_base__dag_clone_child(dag_node_t
noderev->predecessor_id = cur_entry->id;
if (noderev->predecessor_count != -1)
noderev->predecessor_count++;
- noderev->created_path = svn_uri_join(parent_path, name, pool);
+ noderev->created_path = svn_fspath__join(parent_path, name, pool);
SVN_ERR(svn_fs_base__create_successor(&new_node_id, fs, cur_entry->id,
noderev, copy_id, txn_id,
trail, pool));
@@ -1422,7 +1422,7 @@ svn_fs_base__dag_copy(dag_node_t *to_nod
noderev->predecessor_id = svn_fs_base__id_copy(src_id, pool);
if (noderev->predecessor_count != -1)
noderev->predecessor_count++;
- noderev->created_path = svn_uri_join
+ noderev->created_path = svn_fspath__join
(svn_fs_base__dag_get_created_path(to_node), entry, pool);
SVN_ERR(svn_fs_base__create_successor(&id, fs, src_id, noderev,
copy_id, txn_id, trail, pool));
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/fs.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/fs.c Sat Dec 11 00:15:55 2010
@@ -497,6 +497,7 @@ static fs_vtable_t fs_vtable = {
svn_fs_base__get_lock,
svn_fs_base__get_locks,
base_bdb_set_errcall,
+ svn_fs_base__validate_mergeinfo,
};
/* Where the format number is stored. */
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c Sat Dec 11 00:15:55 2010
@@ -250,7 +250,7 @@ svn_fs_base__generate_lock_token(const c
generate a URI that matches the DAV RFC. We could change this to
some other URI scheme someday, if we wish. */
*token = apr_pstrcat(pool, "opaquelocktoken:",
- svn_uuid_generate(pool), NULL);
+ svn_uuid_generate(pool), (char *)NULL);
return SVN_NO_ERROR;
}
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/reps-strings.c Sat Dec 11 00:15:55 2010
@@ -906,10 +906,12 @@ txn_body_read_rep(void *baton, trail_t *
{
representation_t *rep;
- svn_checksum_final(&args->rb->md5_checksum,
- args->rb->md5_checksum_ctx, trail->pool);
- svn_checksum_final(&args->rb->sha1_checksum,
- args->rb->sha1_checksum_ctx, trail->pool);
+ SVN_ERR(svn_checksum_final(&args->rb->md5_checksum,
+ args->rb->md5_checksum_ctx,
+ trail->pool));
+ SVN_ERR(svn_checksum_final(&args->rb->sha1_checksum,
+ args->rb->sha1_checksum_ctx,
+ trail->pool));
args->rb->checksum_finalized = TRUE;
SVN_ERR(svn_fs_bdb__read_rep(&rep, args->rb->fs,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/revs-txns.c Sat Dec 11 00:15:55 2010
@@ -1159,7 +1159,6 @@ svn_fs_base__purge_txn(svn_fs_t *fs,
{
struct cleanup_txn_args args;
transaction_t *txn;
- int i;
SVN_ERR(svn_fs__check_fs(fs, TRUE));
@@ -1182,6 +1181,8 @@ svn_fs_base__purge_txn(svn_fs_t *fs,
/* Kill the transaction's copies (which should gracefully...). */
if (txn->copies)
{
+ int i;
+
for (i = 0; i < txn->copies->nelts; i++)
{
SVN_ERR(svn_fs_base__retry_txn
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c?rev=1044548&r1=1044547&r2=1044548&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c Sat Dec 11 00:15:55 2010
@@ -486,7 +486,7 @@ parent_path_path(parent_path_t *parent_p
if (parent_path->parent)
path_so_far = parent_path_path(parent_path->parent, pool);
return parent_path->entry
- ? svn_uri_join(path_so_far, parent_path->entry, pool)
+ ? svn_fspath__join(path_so_far, parent_path->entry, pool)
: path_so_far;
}
@@ -693,7 +693,7 @@ open_path(parent_path_t **parent_path_p,
entry = svn_fs__next_entry_name(&next, rest, pool);
/* Calculate the path traversed thus far. */
- path_so_far = svn_uri_join(path_so_far, entry, pool);
+ path_so_far = svn_fspath__join(path_so_far, entry, pool);
if (*entry == '\0')
{
@@ -1727,7 +1727,7 @@ deltify_mutable(svn_fs_t *fs,
apr_hash_this(hi, &key, NULL, &val);
entry = val;
SVN_ERR(deltify_mutable(fs, root,
- svn_uri_join(path, key, subpool),
+ svn_fspath__join(path, key, subpool),
entry->id, entry->kind, txn_id, subpool));
}
@@ -1775,7 +1775,7 @@ deltify_mutable(svn_fs_t *fs,
For 1.6 and beyond, we just deltify the current node against its
predecessors, using skip deltas similar to the way FSFS does. */
- int pred_count, nlevels, lev, count;
+ int pred_count;
const svn_fs_id_t *pred_id;
struct txn_pred_count_args tpc_args;
apr_pool_t *subpools[2];
@@ -1861,6 +1861,8 @@ deltify_mutable(svn_fs_t *fs,
}
else
{
+ int nlevels, lev, count;
+
/**** REVERSE DELTA STORAGE ****/
/* Decide how many predecessors to redeltify. To save overhead,
@@ -2269,7 +2271,7 @@ merge(svn_stringbuf_t *conflict_p,
a modification. In any of these cases, flag a conflict. */
if (s_entry == NULL || t_entry == NULL)
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
a_entry->name,
iterpool));
@@ -2284,7 +2286,7 @@ merge(svn_stringbuf_t *conflict_p,
|| strcmp(svn_fs_base__id_copy_id(t_entry->id),
svn_fs_base__id_copy_id(a_entry->id)) != 0)
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
a_entry->name,
iterpool));
@@ -2301,14 +2303,14 @@ merge(svn_stringbuf_t *conflict_p,
|| (svn_fs_base__dag_node_kind(t_ent_node) == svn_node_file)
|| (svn_fs_base__dag_node_kind(a_ent_node) == svn_node_file))
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
a_entry->name,
iterpool));
/* Direct modifications were made to the directory
ANCESTOR-ENTRY in both SOURCE and TARGET. Recursively
merge these modifications. */
- new_tpath = svn_uri_join(target_path, t_entry->name, iterpool);
+ new_tpath = svn_fspath__join(target_path, t_entry->name, iterpool);
SVN_ERR(merge(conflict_p, new_tpath,
t_ent_node, s_ent_node, a_ent_node,
txn_id, &sub_mergeinfo_increment, trail, iterpool));
@@ -2344,7 +2346,7 @@ merge(svn_stringbuf_t *conflict_p,
/* If NAME exists in TARGET, declare a conflict. */
if (t_entry)
return conflict_err(conflict_p,
- svn_uri_join(target_path,
+ svn_fspath__join(target_path,
t_entry->name,
iterpool));
@@ -2520,7 +2522,7 @@ verify_locks(const char *txn_name,
/* If this path has already been verified as part of a recursive
check of one of its parents, no need to do it again. */
if (last_recursed
- && svn_uri_is_child(last_recursed->data, path, subpool))
+ && svn_fspath__is_child(last_recursed->data, path, subpool))
continue;
/* Fetch the change associated with our path. */
@@ -4486,7 +4488,7 @@ txn_body_history_prev(void *baton, trail
if (strcmp(path, copy_dst) == 0)
remainder = "";
else
- remainder = svn_uri_is_child(copy_dst, path, trail->pool);
+ remainder = svn_fspath__is_child(copy_dst, path, trail->pool);
if (remainder)
{
@@ -4499,7 +4501,7 @@ txn_body_history_prev(void *baton, trail
(&dst_rev, fs,
svn_fs_base__id_txn_id(copy->dst_noderev_id),
trail, trail->pool));
- src_path = svn_uri_join(copy->src_path, remainder,
+ src_path = svn_fspath__join(copy->src_path, remainder,
trail->pool);
if (copy->kind == copy_kind_soft)
retry = TRUE;
@@ -4909,8 +4911,8 @@ prev_location(const char **prev_path,
SVN_ERR(base_copied_from(©_src_rev, ©_src_path,
copy_root, copy_path, pool));
if (! strcmp(copy_path, path) == 0)
- remainder = svn_uri_is_child(copy_path, path, pool);
- *prev_path = svn_uri_join(copy_src_path, remainder, pool);
+ remainder = svn_fspath__is_child(copy_path, path, pool);
+ *prev_path = svn_fspath__join(copy_src_path, remainder, pool);
*prev_rev = copy_src_rev;
return SVN_NO_ERROR;
}
@@ -5088,6 +5090,129 @@ base_node_origin_rev(svn_revnum_t *revis
/* Mergeinfo Queries */
+
+/* Implements svn_fs_validate_mergeinfo. */
+svn_error_t *
+svn_fs_base__validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+ svn_fs_t *fs,
+ svn_mergeinfo_t mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_mergeinfo_t filtered_mergeinfo;
+ apr_hash_t *rev_to_sources;
+ apr_hash_index_t *hi;
+ apr_pool_t *iterpool;
+
+ /* A couple easy outs. */
+ if (mergeinfo == NULL)
+ {
+ *validated_mergeinfo = NULL;
+ return SVN_NO_ERROR;
+ }
+ else if (apr_hash_count(mergeinfo) == 0)
+ {
+ *validated_mergeinfo = apr_hash_make(result_pool);
+ return SVN_NO_ERROR;
+ }
+
+ filtered_mergeinfo = apr_hash_make(scratch_pool);
+ rev_to_sources = apr_hash_make(scratch_pool);
+
+ /* Since svn_fs_check_path needs an svn_fs_root_t based on a revision,
+ we convert MERGEINFO into a mapping of revisions to a hash of source
+ paths for efficiency. */
+ for (hi = apr_hash_first(scratch_pool, mergeinfo);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *path = svn__apr_hash_index_key(hi);
+ apr_array_header_t *rangelist = svn__apr_hash_index_val(hi);
+ int i;
+
+ for (i = 0; i < rangelist->nelts; i++)
+ {
+ svn_merge_range_t *range =
+ APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
+ svn_revnum_t j;
+
+ for (j = range->start + 1; j <= range->end; j++)
+ {
+ apr_hash_t *paths_for_rev =
+ apr_hash_get(rev_to_sources, &j, sizeof(svn_revnum_t));
+
+ /* No hash associated with this rev yet? */
+ if (!paths_for_rev)
+ {
+ svn_revnum_t *rev = apr_palloc(scratch_pool, sizeof(*rev));
+
+ *rev = j;
+ paths_for_rev = apr_hash_make(scratch_pool);
+ apr_hash_set(rev_to_sources, rev,
+ sizeof(svn_revnum_t), paths_for_rev);
+ }
+
+ apr_hash_set(paths_for_rev, path, APR_HASH_KEY_STRING, path);
+ }
+ }
+ }
+
+ iterpool = svn_pool_create(scratch_pool);
+
+ /* Validate the rev->source MERGEINFO equivalent hash, building the
+ validated mergeinfo as we go. */
+ for (hi = apr_hash_first(scratch_pool, rev_to_sources);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const svn_revnum_t *rev = svn__apr_hash_index_key(hi);
+ apr_hash_t *paths = svn__apr_hash_index_val(hi);
+ apr_pool_t *inner_iterpool;
+ apr_hash_index_t *hi2;
+ svn_node_kind_t kind;
+ svn_fs_root_t *mergeinfo_rev_root;
+
+ svn_pool_clear(iterpool);
+ inner_iterpool = svn_pool_create(iterpool);
+
+ SVN_ERR(svn_fs_base__revision_root(&mergeinfo_rev_root, fs,
+ *rev, iterpool));
+
+ for (hi2 = apr_hash_first(iterpool, paths);
+ hi2;
+ hi2 = apr_hash_next(hi2))
+ {
+ const char *path = svn__apr_hash_index_key(hi2);
+
+ svn_pool_clear(inner_iterpool);
+ SVN_ERR(base_check_path(&kind, mergeinfo_rev_root,
+ path, inner_iterpool));
+ if (kind == svn_node_none)
+ {
+ apr_hash_set(paths, path, APR_HASH_KEY_STRING, NULL);
+ }
+ else
+ {
+ svn_mergeinfo_t good_mergeinfo_fragment;
+ const char *mergeinfo_str =
+ apr_psprintf(inner_iterpool, "%s:%ld", path, *rev);
+
+ SVN_ERR(svn_mergeinfo_parse(&good_mergeinfo_fragment,
+ mergeinfo_str, scratch_pool));
+ SVN_ERR(svn_mergeinfo_merge(filtered_mergeinfo,
+ good_mergeinfo_fragment,
+ scratch_pool));
+ }
+ }
+ svn_pool_destroy(inner_iterpool);
+ }
+
+ svn_pool_destroy(iterpool);
+ *validated_mergeinfo = svn_mergeinfo_dup(filtered_mergeinfo, result_pool);
+ return SVN_NO_ERROR;
+}
+
+
/* Examine directory NODE's immediately children for mergeinfo.
For those which have explicit mergeinfo, add their mergeinfo to
@@ -5171,7 +5296,7 @@ txn_body_get_mergeinfo_data_and_entries(
SVN_ERR(svn_mergeinfo_parse(&child_mergeinfo, pval->data,
result_pool));
apr_hash_set(args->result_catalog,
- svn_uri_join(args->node_path, dirent->name,
+ svn_fspath__join(args->node_path, dirent->name,
result_pool),
APR_HASH_KEY_STRING,
child_mergeinfo);
@@ -5240,9 +5365,10 @@ crawl_directory_for_mergeinfo(svn_fs_t *
void *val;
svn_pool_clear(iterpool);
apr_hash_this(hi, &key, NULL, &val);
- crawl_directory_for_mergeinfo(fs, val,
- svn_uri_join(node_path, key, iterpool),
- result_catalog, iterpool);
+ SVN_ERR(crawl_directory_for_mergeinfo(fs, val,
+ svn_fspath__join(node_path, key,
+ iterpool),
+ result_catalog, iterpool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -5267,7 +5393,7 @@ append_to_merged_froms(svn_mergeinfo_t *
const void *key;
void *val;
apr_hash_this(hi, &key, NULL, &val);
- apr_hash_set(*output, svn_uri_join(key, rel_path, pool),
+ apr_hash_set(*output, svn_fspath__join(key, rel_path, pool),
APR_HASH_KEY_STRING, svn_rangelist_dup(val, pool));
}
return SVN_NO_ERROR;
@@ -5276,12 +5402,14 @@ append_to_merged_froms(svn_mergeinfo_t *
/* Calculate the mergeinfo for PATH under revision ROOT using
inheritance type INHERIT. Set *MERGEINFO to the mergeinfo, or to
- NULL if there is none. Results are allocated in POOL; TRAIL->pool
+ NULL if there is none. If *MERGEINFO is inherited set *INHERITED
+ to true, false otherwise. Results are allocated in POOL; TRAIL->POOL
is used for temporary allocations. */
struct get_mergeinfo_for_path_baton
{
svn_mergeinfo_t *mergeinfo;
+ svn_boolean_t *inherited;
svn_fs_root_t *root;
const char *path;
svn_mergeinfo_inheritance_t inherit;
@@ -5299,6 +5427,7 @@ txn_body_get_mergeinfo_for_path(void *ba
dag_node_t *node = NULL;
*(args->mergeinfo) = NULL;
+ *(args->inherited) = FALSE;
SVN_ERR(open_path(&parent_path, args->root, args->path, 0,
NULL, trail, trail->pool));
@@ -5380,6 +5509,7 @@ txn_body_get_mergeinfo_for_path(void *ba
nearest_ancestor,
trail->pool),
args->pool));
+ *(args->inherited) = TRUE;
}
return SVN_NO_ERROR;
}
@@ -5411,14 +5541,17 @@ txn_body_get_node_mergeinfo_stats(void *
}
-/* Get the mergeinfo for a set of paths, returned in
- *MERGEINFO_CATALOG. Returned values are allocated in POOL, while
- temporary values are allocated in a sub-pool. */
+/* Get the mergeinfo for a set of paths, returned in *MERGEINFO_CATALOG.
+ If the mergeinfo for any path is inherited and VALIDATE_INHERITED_MERGEINFO
+ is true, then the mergeinfo for that path in *MERGEINFO_CATALOG will only
+ contain path-revs that actually exist in repository. Returned values are
+ allocated in POOL, while temporary values are allocated in a sub-pool. */
static svn_error_t *
get_mergeinfos_for_paths(svn_fs_root_t *root,
svn_mergeinfo_catalog_t *mergeinfo_catalog,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -5429,6 +5562,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *
for (i = 0; i < paths->nelts; i++)
{
svn_mergeinfo_t path_mergeinfo;
+ svn_boolean_t inherited;
struct get_mergeinfo_for_path_baton gmfp_args;
const char *path = APR_ARRAY_IDX(paths, i, const char *);
@@ -5438,6 +5572,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *
/* Get the mergeinfo for PATH itself. */
gmfp_args.mergeinfo = &path_mergeinfo;
+ gmfp_args.inherited = &inherited;
gmfp_args.root = root;
gmfp_args.path = path;
gmfp_args.inherit = inherit;
@@ -5446,9 +5581,16 @@ get_mergeinfos_for_paths(svn_fs_root_t *
txn_body_get_mergeinfo_for_path,
&gmfp_args, FALSE, iterpool));
if (path_mergeinfo)
- apr_hash_set(result_catalog, apr_pstrdup(pool, path),
- APR_HASH_KEY_STRING,
- path_mergeinfo);
+ {
+ if (inherited && validate_inherited_mergeinfo)
+ SVN_ERR(svn_fs_base__validate_mergeinfo(&path_mergeinfo, root->fs,
+ path_mergeinfo, pool,
+ iterpool));
+
+ apr_hash_set(result_catalog, apr_pstrdup(pool, path),
+ APR_HASH_KEY_STRING,
+ path_mergeinfo);
+ }
/* If we're including descendants, do so. */
if (include_descendants)
@@ -5491,6 +5633,7 @@ base_get_mergeinfo(svn_mergeinfo_catalog
svn_fs_root_t *root,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t validate_inherited_mergeinfo,
svn_boolean_t include_descendants,
apr_pool_t *pool)
{
@@ -5504,10 +5647,11 @@ base_get_mergeinfo(svn_mergeinfo_catalog
/* Retrieve a path -> mergeinfo mapping. */
return get_mergeinfos_for_paths(root, catalog, paths,
- inherit, include_descendants,
- pool);
+ inherit, validate_inherited_mergeinfo,
+ include_descendants, pool);
}
+
/* Creating root objects. */