You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2015/09/11 17:51:34 UTC
svn commit: r1702504 [4/19] - in /subversion/branches/reuse-ra-session: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
contrib/hook-scripts/ notes/ subversion/bindings/ctypes-python/csvn/ext/
subversion/bindings/javahl/native/ s...
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_client/resolved.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_client/resolved.c Fri Sep 11 15:51:30 2015
@@ -41,6 +41,9 @@
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
+
+#define ARRAY_LEN(ary) ((sizeof (ary)) / (sizeof ((ary)[0])))
+
/*** Code. ***/
@@ -148,30 +151,1156 @@ svn_client_resolve(const char *path,
/*** Dealing with conflicts. ***/
+struct svn_client_conflict_t
+{
+ const char *local_abspath;
+ svn_client_ctx_t *ctx;
+ apr_hash_t *prop_conflicts;
+
+ /* Indicate which options were chosen to resolve a text or tree conflict
+ * on the conflited node. */
+ svn_client_conflict_option_id_t resolution_text;
+ svn_client_conflict_option_id_t resolution_tree;
+
+ /* A mapping from const char* property name to pointers to
+ * svn_client_conflict_option_t for all properties which had their
+ * conflicts resolved. Indicates which options were chosen to resolve
+ * the property conflicts. */
+ apr_hash_t *resolved_props;
+
+ /* For backwards compat. */
+ const svn_wc_conflict_description2_t *legacy_text_conflict;
+ const svn_wc_conflict_description2_t *legacy_prop_conflict;
+ const svn_wc_conflict_description2_t *legacy_tree_conflict;
+};
+
+/* Resolves conflict to OPTION and sets CONFLICT->RESOLUTION accordingly. */
+typedef svn_error_t *(*conflict_option_resolve_func_t)(
+ svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool);
+
+struct svn_client_conflict_option_t
+{
+ svn_client_conflict_option_id_t id;
+ const char *description;
+
+ svn_client_conflict_t *conflict;
+ conflict_option_resolve_func_t do_resolve_func;
+
+ /* Data which is specific to particular conflicts and options. */
+ union {
+ struct {
+ /* Indicates the property to resolve in case of a property conflict.
+ * If set to "", all properties are resolved to this option. */
+ const char *propname;
+
+ /* A merged property value, if supplied by the API user, else NULL. */
+ const svn_string_t *merged_propval;
+ } prop;
+ } type_data;
+
+};
+
+/*
+ * Return a legacy conflict choice corresponding to OPTION_ID.
+ * Return svn_wc_conflict_choose_undefined if no corresponding
+ * legacy conflict choice exists.
+ */
+static svn_wc_conflict_choice_t
+conflict_option_id_to_wc_conflict_choice(
+ svn_client_conflict_option_id_t option_id)
+{
+
+ switch (option_id)
+ {
+ case svn_client_conflict_option_undefined:
+ return svn_wc_conflict_choose_undefined;
+
+ case svn_client_conflict_option_postpone:
+ return svn_wc_conflict_choose_postpone;
+
+ case svn_client_conflict_option_base_text:
+ return svn_wc_conflict_choose_base;
+
+ case svn_client_conflict_option_incoming_new_text:
+ return svn_wc_conflict_choose_theirs_full;
+
+ case svn_client_conflict_option_working_text:
+ return svn_wc_conflict_choose_mine_full;
+
+ case svn_client_conflict_option_incoming_new_text_for_conflicted_hunks_only:
+ return svn_wc_conflict_choose_theirs_conflict;
+
+ case svn_client_conflict_option_working_text_for_conflicted_hunks_only:
+ return svn_wc_conflict_choose_mine_conflict;
+
+ case svn_client_conflict_option_merged_text:
+ return svn_wc_conflict_choose_merged;
+
+ case svn_client_conflict_option_unspecified:
+ return svn_wc_conflict_choose_unspecified;
+
+ default:
+ break;
+ }
+
+ return svn_wc_conflict_choose_undefined;
+}
+
+static void
+add_legacy_desc_to_conflict(const svn_wc_conflict_description2_t *desc,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool)
+{
+ switch (desc->kind)
+ {
+ case svn_wc_conflict_kind_text:
+ conflict->legacy_text_conflict = desc;
+ break;
+
+ case svn_wc_conflict_kind_property:
+ conflict->legacy_prop_conflict = desc;
+ break;
+
+ case svn_wc_conflict_kind_tree:
+ conflict->legacy_tree_conflict = desc;
+ break;
+
+ default:
+ SVN_ERR_ASSERT_NO_RETURN(FALSE); /* unknown kind of conflict */
+ }
+}
+
+/* Set up a conflict object. If legacy conflict descriptor DESC is not NULL,
+ * set up the conflict object for backwards compatibility. */
+static svn_error_t *
+conflict_get_internal(svn_client_conflict_t **conflict,
+ const char *local_abspath,
+ const svn_wc_conflict_description2_t *desc,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const apr_array_header_t *descs;
+ int i;
+
+ *conflict = apr_pcalloc(result_pool, sizeof(**conflict));
+
+ if (desc)
+ {
+ /* Add a single legacy conflict descriptor. */
+ (*conflict)->local_abspath = desc->local_abspath;
+ (*conflict)->resolution_text = svn_client_conflict_option_undefined;
+ (*conflict)->resolution_tree = svn_client_conflict_option_undefined;
+ (*conflict)->resolved_props = apr_hash_make(result_pool);
+ add_legacy_desc_to_conflict(desc, *conflict, result_pool);
+
+ return SVN_NO_ERROR;
+ }
+
+ (*conflict)->local_abspath = apr_pstrdup(result_pool, local_abspath);
+ (*conflict)->resolution_text = svn_client_conflict_option_undefined;
+ (*conflict)->resolution_tree = svn_client_conflict_option_undefined;
+ (*conflict)->resolved_props = apr_hash_make(result_pool);
+ (*conflict)->ctx = ctx;
+
+ /* Add all legacy conflict descriptors we can find. Eventually, this code
+ * path should stop relying on svn_wc_conflict_description2_t entirely. */
+ SVN_ERR(svn_wc__read_conflict_descriptions2_t(&descs, ctx->wc_ctx,
+ local_abspath,
+ result_pool, scratch_pool));
+ for (i = 0; i < descs->nelts; i++)
+ {
+ desc = APR_ARRAY_IDX(descs, i, const svn_wc_conflict_description2_t *);
+ if (desc->kind == svn_wc_conflict_kind_property)
+ {
+ if ((*conflict)->prop_conflicts == NULL)
+ (*conflict)->prop_conflicts = apr_hash_make(result_pool);
+ svn_hash_sets((*conflict)->prop_conflicts, desc->property_name, desc);
+ }
+ else
+ add_legacy_desc_to_conflict(desc, *conflict, result_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_get(svn_client_conflict_t **conflict,
+ const char *local_abspath,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(conflict_get_internal(conflict, local_abspath, NULL,
+ ctx, result_pool, scratch_pool));
+}
+
+svn_error_t *
+svn_client_conflict_from_wc_description2_t(
+ svn_client_conflict_t **conflict,
+ const svn_wc_conflict_description2_t *desc,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(conflict_get_internal(conflict, NULL, desc, NULL,
+ result_pool, scratch_pool));
+}
+
+/* Baton type for conflict_resolver_func(). */
+struct conflict_resolver_baton_t {
+
+ svn_client_conflict_walk_func_t *conflict_walk_func;
+ void *conflict_walk_func_baton;
+ svn_client_ctx_t *ctx;
+};
+
+/* Implements svn_wc_conflict_resolver_func2_t for now because
+ * libsvn_wc does not support our new conflict type yet. */
+static svn_error_t *
+conflict_resolver_func(svn_wc_conflict_result_t **result,
+ const svn_wc_conflict_description2_t *description,
+ void *baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct conflict_resolver_baton_t *b = baton;
+ svn_client_conflict_t *conflict;
+ const char *local_abspath;
+ svn_client_conflict_option_id_t resolution;
+ svn_wc_conflict_choice_t conflict_choice;
+
+ local_abspath = description->local_abspath;
+ SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, b->ctx,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(b->conflict_walk_func(b->conflict_walk_func_baton,
+ conflict, scratch_pool));
+
+ /* Evaluate the conflict callback result based on which kind
+ * of conflict libsvn_wc has given us. */
+ resolution = svn_client_conflict_option_undefined;
+ if (description->kind == svn_wc_conflict_kind_text)
+ resolution = conflict->resolution_text;
+ else if (description->kind == svn_wc_conflict_kind_tree)
+ resolution = conflict->resolution_tree;
+ else if (description->kind == svn_wc_conflict_kind_property)
+ {
+ svn_client_conflict_option_t *option;
+
+ option = svn_hash_gets(conflict->resolved_props,
+ description->property_name);
+ if (option == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("No resolution provided for conflicted "
+ "property '%s' on path '%s'"),
+ description->property_name,
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+
+ resolution = svn_client_conflict_option_get_id(option);
+ conflict_choice = conflict_option_id_to_wc_conflict_choice(resolution);
+ *result = svn_wc_create_conflict_result(conflict_choice, NULL,
+ result_pool);
+ if (resolution == svn_client_conflict_option_merged_text)
+ (*result)->merged_value = option->type_data.prop.merged_propval;
+
+ return SVN_NO_ERROR;
+ }
+ else
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Unknown legacy conflict kind '%d'"),
+ description->kind);
+
+ if (resolution == svn_client_conflict_option_undefined)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("No resolution for conflicted path '%s'"),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+
+ conflict_choice = conflict_option_id_to_wc_conflict_choice(resolution);
+ *result = svn_wc_create_conflict_result(conflict_choice, NULL, result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_walk(const char *local_abspath,
+ svn_depth_t depth,
+ svn_client_conflict_walk_func_t conflict_walk_func,
+ void *conflict_walk_func_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ struct conflict_resolver_baton_t b;
+ const char *lock_abspath;
+ svn_error_t *err;
+
+ b.conflict_walk_func = conflict_walk_func;
+ b.conflict_walk_func_baton = conflict_walk_func_baton;
+ b.ctx = ctx;
+
+ SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
+ local_abspath,
+ scratch_pool, scratch_pool));
+ /* ### TODO: svn_wc__resolve_conflicts() should be changed to support
+ * ### iteration without relying on svn_wc_conflict_resolver_func2_t */
+ err = svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
+ depth,
+ TRUE /* resolve_text */,
+ "" /* resolve_prop (ALL props) */,
+ TRUE /* resolve_tree */,
+ svn_wc_conflict_choose_unspecified,
+ conflict_resolver_func, &b,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2,
+ scratch_pool);
+
+ err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
+ lock_abspath,
+ scratch_pool));
+ svn_io_sleep_for_timestamps(local_abspath, scratch_pool);
+
+
+
+ return SVN_NO_ERROR;
+}
+
+void
+svn_client_conflict_option_set_merged_propval(
+ svn_client_conflict_option_t *option,
+ const svn_string_t *merged_propval)
+{
+ option->type_data.prop.merged_propval = merged_propval;
+}
+
+/*
+ * Resolve the conflict at LOCAL_ABSPATH. Currently only supports
+ * an OPTION_ID which can be mapped to svn_wc_conflict_choice_t and
+ * maps a single option_id to text, prop, and/or tree conflicts.
+ */
+static svn_error_t *
+resolve_conflict(svn_client_conflict_option_id_t option_id,
+ const char *local_abspath,
+ svn_boolean_t resolve_text,
+ const char * resolve_prop,
+ svn_boolean_t resolve_tree,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc_conflict_choice_t conflict_choice;
+ const char *lock_abspath;
+ svn_error_t *err;
+
+ conflict_choice = conflict_option_id_to_wc_conflict_choice(option_id);
+ SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx,
+ local_abspath,
+ scratch_pool, scratch_pool));
+ err = svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
+ svn_depth_empty,
+ resolve_text, resolve_prop, resolve_tree,
+ conflict_choice,
+ NULL, NULL, /* legacy conflict_func/baton */
+ ctx->cancel_func,
+ ctx->cancel_baton,
+ ctx->notify_func2,
+ ctx->notify_baton2,
+ scratch_pool);
+ err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx,
+ lock_abspath,
+ scratch_pool));
+ svn_io_sleep_for_timestamps(local_abspath, scratch_pool);
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements conflict_option_resolve_func_t. */
+static svn_error_t *
+resolve_text_conflict(svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t option_id;
+ const char *local_abspath;
+
+ option_id = svn_client_conflict_option_get_id(option);
+ local_abspath = svn_client_conflict_get_local_abspath(conflict);
+ SVN_ERR(resolve_conflict(option_id, local_abspath, TRUE, NULL, FALSE,
+ conflict->ctx, scratch_pool));
+ conflict->resolution_text = option_id;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements conflict_option_resolve_func_t. */
+static svn_error_t *
+resolve_prop_conflict(svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t option_id;
+ const char *local_abspath;
+ const char *propname = option->type_data.prop.propname;
+
+ option_id = svn_client_conflict_option_get_id(option);
+ local_abspath = svn_client_conflict_get_local_abspath(conflict);
+ SVN_ERR(resolve_conflict(option_id, local_abspath,
+ FALSE, propname, FALSE,
+ conflict->ctx, scratch_pool));
+
+ if (propname[0] == '\0')
+ {
+ apr_hash_index_t *hi;
+
+ /* All properties have been resolved to the same option. */
+ for (hi = apr_hash_first(scratch_pool, conflict->prop_conflicts);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *this_propname = apr_hash_this_key(hi);
+
+ svn_hash_sets(conflict->resolved_props,
+ apr_pstrdup(apr_hash_pool_get(conflict->resolved_props),
+ this_propname),
+ option);
+ svn_hash_sets(conflict->prop_conflicts, this_propname, NULL);
+ }
+ }
+ else
+ {
+ svn_hash_sets(conflict->resolved_props,
+ apr_pstrdup(apr_hash_pool_get(conflict->resolved_props),
+ propname),
+ option);
+ svn_hash_sets(conflict->prop_conflicts, propname, NULL);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+/* Implements conflict_option_resolve_func_t. */
+resolve_tree_conflict(svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t option_id;
+ const char *local_abspath;
+
+ option_id = svn_client_conflict_option_get_id(option);
+ local_abspath = svn_client_conflict_get_local_abspath(conflict);
+ SVN_ERR(resolve_conflict(option_id, local_abspath, FALSE, NULL, TRUE,
+ conflict->ctx, scratch_pool));
+ conflict->resolution_tree = option_id;
+
+ return SVN_NO_ERROR;
+}
+
+/* Resolver options for a text conflict */
+static const svn_client_conflict_option_t text_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text,
+ N_("accept incoming version of entire file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text,
+ N_("accept working copy version of entire file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text_for_conflicted_hunks_only,
+ N_("accept incoming version of all text conflicts in file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text_for_conflicted_hunks_only,
+ N_("accept working copy version of all text conflicts in file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+};
+
+/* Resolver options for a binary file conflict */
+static const svn_client_conflict_option_t binary_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_text_conflict,
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text,
+ N_("accept incoming version of binary file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text,
+ N_("accept working copy version of binary file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+};
+
+/* Resolver options for a property conflict */
+static const svn_client_conflict_option_t prop_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_prop_conflict
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text,
+ N_("accept incoming version of entire property value"),
+ NULL,
+ resolve_prop_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text,
+ N_("accept working copy version of entire property value"),
+ NULL,
+ resolve_prop_conflict
+ },
+
+};
+
+/* Resolver options for a tree conflict */
+static const svn_client_conflict_option_t tree_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_tree_conflict
+ },
+
+ {
+ /* ### Use 'working text' for now since libsvn_wc does not know another
+ * ### choice to resolve to working yet. */
+ svn_client_conflict_option_working_text,
+ N_("accept current working copy state"),
+ NULL,
+ resolve_tree_conflict
+ },
+
+};
+
+static svn_error_t *
+assert_text_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
+{
+ svn_boolean_t text_conflicted;
+
+ SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, NULL, NULL,
+ conflict, scratch_pool,
+ scratch_pool));
+
+ SVN_ERR_ASSERT(text_conflicted); /* ### return proper error? */
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+assert_prop_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *props_conflicted;
+
+ SVN_ERR(svn_client_conflict_get_conflicted(NULL, &props_conflicted, NULL,
+ conflict, scratch_pool,
+ scratch_pool));
+
+ /* ### return proper error? */
+ SVN_ERR_ASSERT(props_conflicted && props_conflicted->nelts > 0);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+assert_tree_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
+{
+ svn_boolean_t tree_conflicted;
+
+ SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted,
+ conflict, scratch_pool,
+ scratch_pool));
+
+ SVN_ERR_ASSERT(tree_conflicted); /* ### return proper error? */
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_text_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *mime_type;
+ int i;
+
+ SVN_ERR(assert_text_conflict(conflict, scratch_pool));
+
+ *options = apr_array_make(result_pool, ARRAY_LEN(text_conflict_options),
+ sizeof(svn_client_conflict_option_t *));
+
+ mime_type = svn_client_conflict_text_get_mime_type(conflict);
+ if (mime_type && svn_mime_type_is_binary(mime_type))
+ {
+ for (i = 0; i < ARRAY_LEN(binary_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &binary_conflict_options[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < ARRAY_LEN(text_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &text_conflict_options[i];
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_prop_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+
+ SVN_ERR(assert_prop_conflict(conflict, scratch_pool));
+
+ *options = apr_array_make(result_pool, ARRAY_LEN(prop_conflict_options),
+ sizeof(svn_client_conflict_option_t *));
+ for (i = 0; i < ARRAY_LEN(prop_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &prop_conflict_options[i];
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_tree_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+
+ SVN_ERR(assert_tree_conflict(conflict, scratch_pool));
+
+ *options = apr_array_make(result_pool, ARRAY_LEN(tree_conflict_options),
+ sizeof(svn_client_conflict_option_t *));
+ for (i = 0; i < ARRAY_LEN(tree_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &tree_conflict_options[i];
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_client_conflict_option_id_t
+svn_client_conflict_option_get_id(svn_client_conflict_option_t *option)
+{
+ return option->id;
+}
+
+svn_error_t *
+svn_client_conflict_option_describe(const char **description,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *description = apr_pstrdup(result_pool, option->description);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_text_resolve(svn_client_conflict_t *conflict,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(assert_text_conflict(conflict, scratch_pool));
+ SVN_ERR(option->do_resolve_func(option, conflict, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_client_conflict_option_t *
+svn_client_conflict_option_find_by_id(apr_array_header_t *options,
+ svn_client_conflict_option_id_t option_id)
+{
+ int i;
+
+ for (i = 0; i < options->nelts; i++)
+ {
+ svn_client_conflict_option_t *this_option;
+ svn_client_conflict_option_id_t this_option_id;
+
+ this_option = APR_ARRAY_IDX(options, i, svn_client_conflict_option_t *);
+ this_option_id = svn_client_conflict_option_get_id(this_option);
+
+ if (this_option_id == option_id)
+ return this_option;
+ }
+
+ return NULL;
+}
+
+svn_error_t *
+svn_client_conflict_text_resolve_by_id(
+ svn_client_conflict_t *conflict,
+ svn_client_conflict_option_id_t option_id,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *resolution_options;
+ svn_client_conflict_option_t *option;
+
+ SVN_ERR(svn_client_conflict_text_get_resolution_options(
+ &resolution_options, conflict,
+ scratch_pool, scratch_pool));
+ option = svn_client_conflict_option_find_by_id(resolution_options,
+ option_id);
+ if (option == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Inapplicable conflict resolution option "
+ "ID '%d' given for conflicted path '%s'"),
+ option_id,
+ svn_dirent_local_style(conflict->local_abspath,
+ scratch_pool));
+ SVN_ERR(svn_client_conflict_text_resolve(conflict, option, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_client_conflict_option_id_t
+svn_client_conflict_text_get_resolution(const svn_client_conflict_t *conflict)
+{
+ return conflict->resolution_text;
+}
+
+svn_error_t *
+svn_client_conflict_prop_resolve(svn_client_conflict_t *conflict,
+ const char *propname,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(assert_prop_conflict(conflict, scratch_pool));
+ option->type_data.prop.propname = propname;
+ SVN_ERR(option->do_resolve_func(option, conflict, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_prop_resolve_by_id(
+ svn_client_conflict_t *conflict,
+ const char *propname,
+ svn_client_conflict_option_id_t option_id,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *resolution_options;
+ svn_client_conflict_option_t *option;
+
+ SVN_ERR(svn_client_conflict_prop_get_resolution_options(
+ &resolution_options, conflict,
+ scratch_pool, scratch_pool));
+ option = svn_client_conflict_option_find_by_id(resolution_options,
+ option_id);
+ if (option == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Inapplicable conflict resolution option "
+ "ID '%d' given for conflicted path '%s'"),
+ option_id,
+ svn_dirent_local_style(conflict->local_abspath,
+ scratch_pool));
+ SVN_ERR(svn_client_conflict_prop_resolve(conflict, propname, option,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_client_conflict_option_id_t
+svn_client_conflict_prop_get_resolution(const svn_client_conflict_t *conflict,
+ const char *propname)
+{
+ svn_client_conflict_option_t *option;
+
+ option = svn_hash_gets(conflict->resolved_props, propname);
+ if (option == NULL)
+ return svn_client_conflict_option_undefined;
+
+ return svn_client_conflict_option_get_id(option);
+}
+
+svn_error_t *
+svn_client_conflict_tree_resolve(svn_client_conflict_t *conflict,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(assert_tree_conflict(conflict, scratch_pool));
+ SVN_ERR(option->do_resolve_func(option, conflict, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_tree_resolve_by_id(
+ svn_client_conflict_t *conflict,
+ svn_client_conflict_option_id_t option_id,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *resolution_options;
+ svn_client_conflict_option_t *option;
+
+ SVN_ERR(svn_client_conflict_tree_get_resolution_options(
+ &resolution_options, conflict,
+ scratch_pool, scratch_pool));
+ option = svn_client_conflict_option_find_by_id(resolution_options,
+ option_id);
+ if (option == NULL)
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+ _("Inapplicable conflict resolution option "
+ "ID '%d' given for conflicted path '%s'"),
+ option_id,
+ svn_dirent_local_style(conflict->local_abspath,
+ scratch_pool));
+ SVN_ERR(svn_client_conflict_tree_resolve(conflict, option, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_client_conflict_option_id_t
+svn_client_conflict_tree_get_resolution(const svn_client_conflict_t *conflict)
+{
+ return conflict->resolution_tree;
+}
+
+/* Return the legacy conflict descriptor which is wrapped by CONFLICT. */
+static const svn_wc_conflict_description2_t *
+get_conflict_desc2_t(const svn_client_conflict_t *conflict)
+{
+ if (conflict->legacy_text_conflict)
+ return conflict->legacy_text_conflict;
+
+ if (conflict->legacy_tree_conflict)
+ return conflict->legacy_tree_conflict;
+
+ if (conflict->legacy_prop_conflict)
+ return conflict->legacy_prop_conflict;
+
+ return NULL;
+}
+
+svn_wc_conflict_kind_t
+svn_client_conflict_get_kind(const svn_client_conflict_t *conflict)
+{
+ return get_conflict_desc2_t(conflict)->kind;
+}
+
+svn_error_t *
+svn_client_conflict_get_conflicted(svn_boolean_t *text_conflicted,
+ apr_array_header_t **props_conflicted,
+ svn_boolean_t *tree_conflicted,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (text_conflicted)
+ *text_conflicted = (conflict->legacy_text_conflict != NULL);
+
+ if (props_conflicted)
+ {
+ if (conflict->legacy_prop_conflict)
+ {
+ *props_conflicted = apr_array_make(result_pool, 1,
+ sizeof(const char*));
+ APR_ARRAY_PUSH((*props_conflicted), const char *) =
+ conflict->legacy_prop_conflict->property_name;
+ }
+ else if (conflict->prop_conflicts)
+ SVN_ERR(svn_hash_keys(props_conflicted, conflict->prop_conflicts,
+ result_pool));
+ else
+ *props_conflicted = NULL;
+ }
+
+ if (tree_conflicted)
+ *tree_conflicted = (conflict->legacy_tree_conflict != NULL);
+
+ return SVN_NO_ERROR;
+}
+
const char *
-svn_client_conflict_get_local_abspath(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_local_abspath(const svn_client_conflict_t *conflict)
{
return conflict->local_abspath;
}
svn_wc_operation_t
-svn_client_conflict_get_operation(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_operation(const svn_client_conflict_t *conflict)
{
- return conflict->operation;
+ return get_conflict_desc2_t(conflict)->operation;
}
svn_wc_conflict_action_t
-svn_client_conflict_get_incoming_change(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_incoming_change(const svn_client_conflict_t *conflict)
{
- return conflict->action;
+ return get_conflict_desc2_t(conflict)->action;
}
svn_wc_conflict_reason_t
-svn_client_conflict_get_local_change(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_local_change(const svn_client_conflict_t *conflict)
+{
+ return get_conflict_desc2_t(conflict)->reason;
+}
+
+svn_error_t *
+svn_client_conflict_get_repos_info(const char **repos_root_url,
+ const char **repos_uuid,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- return conflict->reason;
+ if (repos_root_url)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *repos_root_url =
+ get_conflict_desc2_t(conflict)->src_left_version->repos_url;
+ else if (get_conflict_desc2_t(conflict)->src_right_version)
+ *repos_root_url =
+ get_conflict_desc2_t(conflict)->src_right_version->repos_url;
+ else
+ *repos_root_url = NULL;
+ }
+
+ if (repos_uuid)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *repos_uuid =
+ get_conflict_desc2_t(conflict)->src_left_version->repos_uuid;
+ else if (get_conflict_desc2_t(conflict)->src_right_version)
+ *repos_uuid =
+ get_conflict_desc2_t(conflict)->src_right_version->repos_uuid;
+ else
+ *repos_uuid = NULL;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_get_incoming_old_repos_location(
+ const char **incoming_old_repos_relpath,
+ svn_revnum_t *incoming_old_pegrev,
+ svn_node_kind_t *incoming_old_node_kind,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (incoming_old_repos_relpath)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *incoming_old_repos_relpath =
+ get_conflict_desc2_t(conflict)->src_left_version->path_in_repos;
+ else
+ *incoming_old_repos_relpath = NULL;
+ }
+
+ if (incoming_old_pegrev)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *incoming_old_pegrev =
+ get_conflict_desc2_t(conflict)->src_left_version->peg_rev;
+ else
+ *incoming_old_pegrev = SVN_INVALID_REVNUM;
+ }
+
+ if (incoming_old_node_kind)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *incoming_old_node_kind =
+ get_conflict_desc2_t(conflict)->src_left_version->node_kind;
+ else
+ *incoming_old_node_kind = svn_node_none;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_get_incoming_new_repos_location(
+ const char **incoming_new_repos_relpath,
+ svn_revnum_t *incoming_new_pegrev,
+ svn_node_kind_t *incoming_new_node_kind,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (incoming_new_repos_relpath)
+ {
+ if (get_conflict_desc2_t(conflict)->src_right_version)
+ *incoming_new_repos_relpath =
+ get_conflict_desc2_t(conflict)->src_right_version->path_in_repos;
+ else
+ *incoming_new_repos_relpath = NULL;
+ }
+
+ if (incoming_new_pegrev)
+ {
+ if (get_conflict_desc2_t(conflict)->src_right_version)
+ *incoming_new_pegrev =
+ get_conflict_desc2_t(conflict)->src_right_version->peg_rev;
+ else
+ *incoming_new_pegrev = SVN_INVALID_REVNUM;
+ }
+
+ if (incoming_new_node_kind)
+ {
+ if (get_conflict_desc2_t(conflict)->src_right_version)
+ *incoming_new_node_kind =
+ get_conflict_desc2_t(conflict)->src_right_version->node_kind;
+ else
+ *incoming_new_node_kind = svn_node_none;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_node_kind_t
+svn_client_conflict_tree_get_victim_node_kind(
+ const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_tree);
+
+ return get_conflict_desc2_t(conflict)->node_kind;
+}
+
+const char *
+svn_client_conflict_prop_get_propname(const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_property);
+
+ return get_conflict_desc2_t(conflict)->property_name;
+}
+
+svn_error_t *
+svn_client_conflict_prop_get_propvals(const svn_string_t **base_propval,
+ const svn_string_t **working_propval,
+ const svn_string_t **incoming_old_propval,
+ const svn_string_t **incoming_new_propval,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool)
+{
+ SVN_ERR_ASSERT(svn_client_conflict_get_kind(conflict) ==
+ svn_wc_conflict_kind_property);
+
+ if (base_propval)
+ *base_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_base,
+ result_pool);
+
+ if (working_propval)
+ *working_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_working,
+ result_pool);
+
+ if (incoming_old_propval)
+ *incoming_old_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_incoming_old,
+ result_pool);
+
+ if (incoming_new_propval)
+ *incoming_new_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_incoming_new,
+ result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+const char *
+svn_client_conflict_prop_get_reject_abspath(
+ const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_property);
+
+ /* svn_wc_conflict_description2_t stores this path in 'their_abspath' */
+ return get_conflict_desc2_t(conflict)->their_abspath;
+}
+
+const char *
+svn_client_conflict_text_get_mime_type(const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_text);
+
+ return get_conflict_desc2_t(conflict)->mime_type;
+}
+
+svn_error_t *
+svn_client_conflict_text_get_contents(const char **base_abspath,
+ const char **working_abspath,
+ const char **incoming_old_abspath,
+ const char **incoming_new_abspath,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR_ASSERT(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_text);
+
+ if (base_abspath)
+ {
+ if (svn_client_conflict_get_operation(conflict) ==
+ svn_wc_operation_merge)
+ *base_abspath = NULL; /* ### WC base contents not available yet */
+ else /* update/switch */
+ *base_abspath = get_conflict_desc2_t(conflict)->base_abspath;
+ }
+
+ if (working_abspath)
+ *working_abspath = get_conflict_desc2_t(conflict)->my_abspath;
+
+ if (incoming_old_abspath)
+ *incoming_old_abspath = get_conflict_desc2_t(conflict)->base_abspath;
+
+ if (incoming_new_abspath)
+ *incoming_new_abspath = get_conflict_desc2_t(conflict)->their_abspath;
+
+ return SVN_NO_ERROR;
}
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_client/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_client/upgrade.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_client/upgrade.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_client/upgrade.c Fri Sep 11 15:51:30 2015
@@ -83,11 +83,13 @@ fetch_repos_info(const char **repos_root
}
/* Forward definition. Upgrades svn:externals properties in the working copy
- LOCAL_ABSPATH to the WC-NG storage.
+ LOCAL_ABSPATH to the WC-NG storage. INFO_BATON will be used to fetch
+ repository info using fetch_repos_info() function if needed.
*/
static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
+ struct repos_info_baton *info_baton,
apr_pool_t *scratch_pool);
svn_error_t *
@@ -172,7 +174,7 @@ svn_client_upgrade(const char *path,
(There is no way to detect the difference from libsvn_client :( ) */
SVN_ERR(upgrade_externals_from_properties(ctx, local_abspath,
- scratch_pool));
+ &info_baton, scratch_pool));
}
return SVN_NO_ERROR;
}
@@ -180,6 +182,7 @@ svn_client_upgrade(const char *path,
static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
+ struct repos_info_baton *info_baton,
apr_pool_t *scratch_pool)
{
apr_hash_index_t *hi;
@@ -187,7 +190,6 @@ upgrade_externals_from_properties(svn_cl
apr_pool_t *iterpool2;
apr_hash_t *externals;
svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
- struct repos_info_baton info_baton;
/* Now it's time to upgrade the externals too. We do it after the wc
upgrade to avoid that errors in the externals causes the wc upgrade to
@@ -345,7 +347,7 @@ upgrade_externals_from_properties(svn_cl
{
err = fetch_repos_info(&repos_root_url,
&repos_uuid,
- &info_baton,
+ info_baton,
resolved_url,
scratch_pool, scratch_pool);
if (err)
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_diff/parse-diff.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_diff/parse-diff.c Fri Sep 11 15:51:30 2015
@@ -1352,17 +1352,22 @@ static struct transition transitions[] =
{
{"--- ", state_start, diff_minus},
{"+++ ", state_minus_seen, diff_plus},
+
{"diff --git", state_start, git_start},
{"--- a/", state_git_diff_seen, git_minus},
{"--- a/", state_git_tree_seen, git_minus},
{"--- /dev/null", state_git_tree_seen, git_minus},
{"+++ b/", state_git_minus_seen, git_plus},
{"+++ /dev/null", state_git_minus_seen, git_plus},
+
{"rename from ", state_git_diff_seen, git_move_from},
{"rename to ", state_move_from_seen, git_move_to},
+
{"copy from ", state_git_diff_seen, git_copy_from},
{"copy to ", state_copy_from_seen, git_copy_to},
+
{"new file ", state_git_diff_seen, git_new_file},
+
{"deleted file ", state_git_diff_seen, git_deleted_file},
};
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.c Fri Sep 11 15:51:30 2015
@@ -1773,8 +1773,7 @@ svn_fs_lock_target_create(const char *to
svn_revnum_t current_rev,
apr_pool_t *result_pool)
{
- svn_fs_lock_target_t *target = apr_palloc(result_pool,
- sizeof(svn_fs_lock_target_t));
+ svn_fs_lock_target_t *target = apr_palloc(result_pool, sizeof(*target));
target->token = token;
target->current_rev = current_rev;
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.h?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs/fs-loader.h Fri Sep 11 15:51:30 2015
@@ -22,8 +22,8 @@
*/
-#ifndef LIBSVN_FS_FS_H
-#define LIBSVN_FS_FS_H
+#ifndef LIBSVN_FS_LOADER_H
+#define LIBSVN_FS_LOADER_H
#include "svn_types.h"
#include "svn_fs.h"
@@ -184,15 +184,9 @@ typedef svn_error_t *(*fs_init_func_t)(c
to the create and open functions and these init functions (as well
as the open and create functions) are globally serialized so that
they have exclusive access to the common_pool. */
-svn_error_t *svn_fs_base__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
-svn_error_t *svn_fs_fs__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
-svn_error_t *svn_fs_x__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
+#include "../libsvn_fs_base/fs_init.h"
+#include "../libsvn_fs_fs/fs_init.h"
+#include "../libsvn_fs_x/fs_init.h"
@@ -569,4 +563,4 @@ struct svn_fs_lock_target_t
}
#endif /* __cplusplus */
-#endif
+#endif /* LIBSVN_FS_LOADER_H */
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_base/revs-txns.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_base/revs-txns.c Fri Sep 11 15:51:30 2015
@@ -247,8 +247,10 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
{
transaction_t *txn;
const char *txn_id;
+ const svn_string_t *present_value;
SVN_ERR(get_rev_txn(&txn, &txn_id, fs, rev, trail, pool));
+ present_value = svn_hash_gets(txn->proplist, name);
/* If there's no proplist, but we're just deleting a property, exit now. */
if ((! txn->proplist) && (! value))
@@ -262,7 +264,6 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
if (old_value_p)
{
const svn_string_t *wanted_value = *old_value_p;
- const svn_string_t *present_value = svn_hash_gets(txn->proplist, name);
if ((!wanted_value != !present_value)
|| (wanted_value && present_value
&& !svn_string_compare(wanted_value, present_value)))
@@ -275,6 +276,13 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
}
/* Fall through. */
}
+
+ /* If the prop-set is a no-op, skip the actual write. */
+ if ((!present_value && !value)
+ || (present_value && value
+ && svn_string_compare(present_value, value)))
+ return SVN_NO_ERROR;
+
svn_hash_sets(txn->proplist, name, value);
/* Overwrite the revision. */
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/cached_data.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/cached_data.c Fri Sep 11 15:51:30 2015
@@ -57,7 +57,7 @@ block_read(void **result,
apr_pool_t *scratch_pool);
-/* Defined this to enable access logging via dgb__log_access
+/* Define this to enable access logging via dbg_log_access
#define SVN_FS_FS__LOG_ACCESS
*/
@@ -91,7 +91,7 @@ dbg_log_access(svn_fs_t *fs,
svn_fs_fs__revision_file_t *rev_file;
SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, revision,
- scratch_pool));
+ scratch_pool, scratch_pool));
/* determine rev / pack file offset */
SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev_file, revision, NULL,
@@ -158,7 +158,8 @@ dbg_log_access(svn_fs_t *fs,
{
/* reverse index lookup: get item description in ENTRY */
SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, revision,
- offset, scratch_pool));
+ offset, scratch_pool,
+ scratch_pool));
if (entry)
{
/* more details */
@@ -183,6 +184,10 @@ dbg_log_access(svn_fs_t *fs,
description);
}
+ /* We don't know when SCRATCH_POOL will be cleared, so close the rev file
+ explicitly. */
+ SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
+
#endif
return SVN_NO_ERROR;
@@ -2862,7 +2867,7 @@ svn_fs_fs__get_changes(apr_array_header_
svn_revnum_t rev,
apr_pool_t *result_pool)
{
- apr_off_t changes_offset = SVN_FS_FS__ITEM_INDEX_CHANGES;
+ apr_off_t item_index = SVN_FS_FS__ITEM_INDEX_CHANGES;
svn_fs_fs__revision_file_t *revision_file;
svn_boolean_t found;
fs_fs_data_t *ffd = fs->fsap_data;
@@ -2897,17 +2902,26 @@ svn_fs_fs__get_changes(apr_array_header_
}
else
{
+ apr_off_t changes_offset;
+
/* Addressing is very different for old formats
* (needs to read the revision trailer). */
if (svn_fs_fs__use_log_addressing(fs))
- SVN_ERR(svn_fs_fs__item_offset(&changes_offset, fs,
- revision_file, rev, NULL,
- SVN_FS_FS__ITEM_INDEX_CHANGES,
- scratch_pool));
+ {
+ SVN_ERR(svn_fs_fs__item_offset(&changes_offset, fs,
+ revision_file, rev, NULL,
+ SVN_FS_FS__ITEM_INDEX_CHANGES,
+ scratch_pool));
+ }
else
- SVN_ERR(get_root_changes_offset(NULL, &changes_offset,
- revision_file, fs, rev,
- scratch_pool));
+ {
+ SVN_ERR(get_root_changes_offset(NULL, &changes_offset,
+ revision_file, fs, rev,
+ scratch_pool));
+
+ /* This variable will be used for debug logging only. */
+ item_index = changes_offset;
+ }
/* Actual reading and parsing are the same, though. */
SVN_ERR(aligned_seek(fs, revision_file->file, NULL, changes_offset,
@@ -2935,7 +2949,7 @@ svn_fs_fs__get_changes(apr_array_header_
SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
}
- SVN_ERR(dbg_log_access(fs, rev, changes_offset, *changes,
+ SVN_ERR(dbg_log_access(fs, rev, item_index, *changes,
SVN_FS_FS__ITEM_TYPE_CHANGES, scratch_pool));
svn_pool_destroy(scratch_pool);
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/caching.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/caching.c Fri Sep 11 15:51:30 2015
@@ -274,7 +274,8 @@ init_callbacks(svn_cache__t *cache,
* MEMBUFFER is not NULL. Fallbacks to inprocess cache if MEMCACHE and
* MEMBUFFER are NULL and pages is non-zero. Sets *CACHE_P to NULL
* otherwise. Use the given PRIORITY class for the new cache. If it
- * is 0, then use the default priority class.
+ * is 0, then use the default priority class. HAS_NAMESPACE indicates
+ * whether we prefixed this cache instance with a namespace.
*
* Unless NO_HANDLER is true, register an error handler that reports errors
* as warnings to the FS warning callback.
@@ -292,6 +293,7 @@ create_cache(svn_cache__t **cache_p,
apr_ssize_t klen,
const char *prefix,
apr_uint32_t priority,
+ svn_boolean_t has_namespace,
svn_fs_t *fs,
svn_boolean_t no_handler,
apr_pool_t *result_pool,
@@ -314,9 +316,12 @@ create_cache(svn_cache__t **cache_p,
}
else if (membuffer)
{
+ /* We assume caches with namespaces to be relatively short-lived,
+ * i.e. their data will not be needed after a while. */
SVN_ERR(svn_cache__create_membuffer_cache(
cache_p, membuffer, serializer, deserializer,
- klen, prefix, priority, FALSE, result_pool, scratch_pool));
+ klen, prefix, priority, FALSE, has_namespace,
+ result_pool, scratch_pool));
}
else if (pages)
{
@@ -349,6 +354,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
svn_boolean_t cache_txdeltas;
svn_boolean_t cache_fulltexts;
const char *cache_namespace;
+ svn_boolean_t has_namespace;
/* Evaluating the cache configuration. */
SVN_ERR(read_config(&cache_namespace,
@@ -358,6 +364,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
pool));
prefix = apr_pstrcat(pool, "ns:", cache_namespace, ":", prefix, SVN_VA_NULL);
+ has_namespace = strlen(cache_namespace) > 0;
membuffer = svn_cache__get_global_membuffer_cache();
@@ -386,34 +393,35 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
* commands, this is only going to contain a few entries (svnadmin
* dump/verify is an exception here), so to reduce overhead let's
* try to keep it to just one page. I estimate each entry has about
- * 72 bytes of overhead (svn_revnum_t key, svn_fs_id_t +
- * id_private_t + 3 strings for value, and the cache_entry); the
- * default pool size is 8192, so about a hundred should fit
- * comfortably. */
+ * 130 bytes of overhead (svn_revnum_t key, ID struct, and the cache_entry);
+ * the default pool size is 8192, so about a fifty should fit comfortably.
+ */
SVN_ERR(create_cache(&(ffd->rev_root_id_cache),
NULL,
membuffer,
- 1, 100,
+ 1, 50,
svn_fs_fs__serialize_id,
svn_fs_fs__deserialize_id,
sizeof(svn_revnum_t),
apr_pstrcat(pool, prefix, "RRI", SVN_VA_NULL),
0,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
- /* Rough estimate: revision DAG nodes have size around 320 bytes, so
- * let's put 16 on a page. */
+ /* Rough estimate: revision DAG nodes have size around 1kBytes, so
+ * let's put 8 on a page. */
SVN_ERR(create_cache(&(ffd->rev_node_cache),
NULL,
membuffer,
- 1024, 16,
+ 1, 8,
svn_fs_fs__dag_serialize,
svn_fs_fs__dag_deserialize,
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "DAG", SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -425,28 +433,30 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->dir_cache),
NULL,
membuffer,
- 1024, 8,
+ 1, 8,
svn_fs_fs__serialize_dir_entries,
svn_fs_fs__deserialize_dir_entries,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "DIR", SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
- /* Only 16 bytes per entry (a revision number + the corresponding offset).
- Since we want ~8k pages, that means 512 entries per page. */
+ /* 8 kBytes per entry (1000 revs / shared, one file offset per rev).
+ Covering about 8 pack files gives us an "o.k." hit rate. */
SVN_ERR(create_cache(&(ffd->packed_offset_cache),
NULL,
membuffer,
- 32, 1,
+ 8, 1,
svn_fs_fs__serialize_manifest,
svn_fs_fs__deserialize_manifest,
sizeof(svn_revnum_t),
apr_pstrcat(pool, prefix, "PACK-MANIFEST",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -455,12 +465,13 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->node_revision_cache),
NULL,
membuffer,
- 32, 32, /* ~200 byte / entry; 1k entries total */
+ 2, 16, /* ~500 byte / entry; 32 entries total */
svn_fs_fs__serialize_node_revision,
svn_fs_fs__deserialize_node_revision,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "NODEREVS", SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -469,12 +480,13 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->rep_header_cache),
NULL,
membuffer,
- 1, 1000, /* ~8 bytes / entry; 1k entries total */
+ 1, 200, /* ~40 bytes / entry; 200 entries total */
svn_fs_fs__serialize_rep_header,
svn_fs_fs__deserialize_rep_header,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "REPHEADER", SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -489,6 +501,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
sizeof(svn_revnum_t),
apr_pstrcat(pool, prefix, "CHANGES", SVN_VA_NULL),
0,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -499,12 +512,13 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->fulltext_cache),
ffd->memcache,
membuffer,
- 0, 0, /* Do not use inprocess cache */
+ 0, 0, /* Do not use the inprocess cache */
/* Values are svn_stringbuf_t */
NULL, NULL,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "TEXT", SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -512,13 +526,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->properties_cache),
NULL,
membuffer,
- 0, 0, /* Do not use inprocess cache */
+ 0, 0, /* Do not use the inprocess cache */
svn_fs_fs__serialize_properties,
svn_fs_fs__deserialize_properties,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "PROP",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -526,13 +541,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->mergeinfo_cache),
NULL,
membuffer,
- 0, 0, /* Do not use inprocess cache */
+ 0, 0, /* Do not use the inprocess cache */
svn_fs_fs__serialize_mergeinfo,
svn_fs_fs__deserialize_mergeinfo,
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "MERGEINFO",
SVN_VA_NULL),
0,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -540,13 +556,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->mergeinfo_existence_cache),
NULL,
membuffer,
- 0, 0, /* Do not use inprocess cache */
+ 0, 0, /* Do not use the inprocess cache */
/* Values are svn_stringbuf_t */
NULL, NULL,
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "HAS_MERGEINFO",
SVN_VA_NULL),
0,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -565,13 +582,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->raw_window_cache),
NULL,
membuffer,
- 0, 0, /* Do not use inprocess cache */
+ 0, 0, /* Do not use the inprocess cache */
svn_fs_fs__serialize_raw_window,
svn_fs_fs__deserialize_raw_window,
sizeof(window_cache_key_t),
apr_pstrcat(pool, prefix, "RAW_WINDOW",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -579,13 +597,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->txdelta_window_cache),
NULL,
membuffer,
- 0, 0, /* Do not use inprocess cache */
+ 0, 0, /* Do not use the inprocess cache */
svn_fs_fs__serialize_txdelta_window,
svn_fs_fs__deserialize_txdelta_window,
sizeof(window_cache_key_t),
apr_pstrcat(pool, prefix, "TXDELTA_WINDOW",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -593,13 +612,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->combined_window_cache),
NULL,
membuffer,
- 0, 0, /* Do not use inprocess cache */
+ 0, 0, /* Do not use the inprocess cache */
/* Values are svn_stringbuf_t */
NULL, NULL,
sizeof(window_cache_key_t),
apr_pstrcat(pool, prefix, "COMBINED_WINDOW",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -613,28 +633,34 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(create_cache(&(ffd->l2p_header_cache),
NULL,
membuffer,
- 64, 16, /* entry size varies but we must cover
- a reasonable number of revisions (1k) */
+ 8, 16, /* entry size varies but we must cover a
+ reasonable number of rev / pack files
+ to allow for delta chains to be walked
+ efficiently etc. */
svn_fs_fs__serialize_l2p_header,
svn_fs_fs__deserialize_l2p_header,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "L2P_HEADER",
(char *)NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
SVN_ERR(create_cache(&(ffd->l2p_page_cache),
NULL,
membuffer,
- 64, 16, /* entry size varies but we must cover
- a reasonable number of revisions (1k) */
+ 8, 16, /* entry size varies but we must cover a
+ reasonable number of rev / pack files
+ to allow for delta chains to be walked
+ efficiently etc. */
svn_fs_fs__serialize_l2p_page,
svn_fs_fs__deserialize_l2p_page,
sizeof(svn_fs_fs__page_cache_key_t),
apr_pstrcat(pool, prefix, "L2P_PAGE",
(char *)NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -648,19 +674,21 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
apr_pstrcat(pool, prefix, "P2L_HEADER",
(char *)NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
SVN_ERR(create_cache(&(ffd->p2l_page_cache),
NULL,
membuffer,
- 4, 16, /* Variably sized entries. Rarely used. */
+ 4, 1, /* Variably sized entries. Rarely used. */
svn_fs_fs__serialize_p2l_page,
svn_fs_fs__deserialize_p2l_page,
sizeof(svn_fs_fs__page_cache_key_t),
apr_pstrcat(pool, prefix, "P2L_PAGE",
(char *)NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
no_handler,
fs->pool, pool));
@@ -807,6 +835,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
apr_pstrcat(pool, prefix, "TXNDIR",
SVN_VA_NULL),
0,
+ TRUE, /* The TXN-ID is our namespace. */
fs,
TRUE,
pool, pool));
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.c Fri Sep 11 15:51:30 2015
@@ -134,6 +134,18 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_fs_fs__initialize_shared_data(svn_fs_t *fs,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool)
+{
+ SVN_MUTEX__WITH_LOCK(common_pool_lock,
+ fs_serialized_init(fs, common_pool, pool));
+
+ return SVN_NO_ERROR;
+}
+
/* This function is provided for Subversion 1.0.x compatibility. It
@@ -480,28 +492,19 @@ fs_hotcopy(svn_fs_t *src_fs,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
- /* Open the source repo as usual. */
SVN_ERR(fs_open(src_fs, src_path, common_pool_lock, pool, common_pool));
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
- /* Test target repo when in INCREMENTAL mode, initialize it when not.
- * For this, we need our FS internal data structures to be temporarily
- * available. */
+ SVN_ERR(svn_fs__check_fs(dst_fs, FALSE));
SVN_ERR(initialize_fs_struct(dst_fs));
- SVN_ERR(svn_fs_fs__hotcopy_prepare_target(src_fs, dst_fs, dst_path,
- incremental, pool));
- uninitialize_fs_struct(dst_fs);
-
- /* Now, the destination repo should open just fine. */
- SVN_ERR(fs_open(dst_fs, dst_path, common_pool_lock, pool, common_pool));
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- /* Now, we may copy data as needed ... */
- return svn_fs_fs__hotcopy(src_fs, dst_fs, incremental,
- notify_func, notify_baton,
- cancel_func, cancel_baton, pool);
+
+ /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS.
+ Otherwise, it's not an FS yet --- possibly just an empty dir --- so
+ can't be opened.
+ */
+ return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path,
+ incremental, notify_func, notify_baton,
+ cancel_func, cancel_baton, common_pool_lock,
+ pool, common_pool);
}
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.h?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs.h Fri Sep 11 15:51:30 2015
@@ -82,8 +82,6 @@ extern "C" {
/* Names of special files and file extensions for transactions */
#define PATH_CHANGES "changes" /* Records changes made so far */
#define PATH_TXN_PROPS "props" /* Transaction properties */
-#define PATH_TXN_PROPS_FINAL "props-final" /* Final transaction properties
- before moving to revprops */
#define PATH_NEXT_IDS "next-ids" /* Next temporary ID assignments */
#define PATH_PREFIX_NODE "node." /* Prefix for node filename */
#define PATH_EXT_TXN ".txn" /* Extension of txn dir */
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.c Fri Sep 11 15:51:30 2015
@@ -2010,7 +2010,7 @@ set_node_origins_for_file(svn_fs_t *fs,
SVN_ERR(svn_stream_close(stream));
/* Rename the temp file as the real destination */
- return svn_io_file_rename(path_tmp, node_origins_path, pool);
+ return svn_io_file_rename2(path_tmp, node_origins_path, FALSE, pool);
}
@@ -2075,13 +2075,14 @@ change_rev_prop_body(void *baton, apr_po
{
struct change_rev_prop_baton *cb = baton;
apr_hash_t *table;
+ const svn_string_t *present_value;
SVN_ERR(svn_fs_fs__get_revision_proplist(&table, cb->fs, cb->rev, pool));
+ present_value = svn_hash_gets(table, cb->name);
if (cb->old_value_p)
{
const svn_string_t *wanted_value = *cb->old_value_p;
- const svn_string_t *present_value = svn_hash_gets(table, cb->name);
if ((!wanted_value != !present_value)
|| (wanted_value && present_value
&& !svn_string_compare(wanted_value, present_value)))
@@ -2094,6 +2095,13 @@ change_rev_prop_body(void *baton, apr_po
}
/* Fall through. */
}
+
+ /* If the prop-set is a no-op, skip the actual write. */
+ if ((!present_value && !cb->value)
+ || (present_value && cb->value
+ && svn_string_compare(present_value, cb->value)))
+ return SVN_NO_ERROR;
+
svn_hash_sets(table, cb->name, cb->value);
return svn_fs_fs__set_revision_proplist(cb->fs, cb->rev, table, pool);
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.h?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/fs_fs.h Fri Sep 11 15:51:30 2015
@@ -39,6 +39,15 @@ svn_error_t *svn_fs_fs__open(svn_fs_t *f
const char *path,
apr_pool_t *pool);
+/* Initialize parts of the FS data that are being shared across multiple
+ filesystem objects. Use COMMON_POOL for process-wide and POOL for
+ temporary allocations. Use COMMON_POOL_LOCK to ensure that the
+ initialization is serialized. */
+svn_error_t *svn_fs_fs__initialize_shared_data(svn_fs_t *fs,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool);
+
/* Upgrade the fsfs filesystem FS. Indicate progress via the optional
* NOTIFY_FUNC callback using NOTIFY_BATON. The optional CANCEL_FUNC
* will periodically be called with CANCEL_BATON to allow for preemption.
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.c Fri Sep 11 15:51:30 2015
@@ -982,6 +982,10 @@ hotcopy_body(void *baton, apr_pool_t *po
if (kind == svn_node_file)
{
SVN_ERR(svn_sqlite__hotcopy(src_subdir, dst_subdir, pool));
+
+ /* The source might have r/o flags set on it - which would be
+ carried over to the copy. */
+ SVN_ERR(svn_io_set_file_read_write(dst_subdir, FALSE, pool));
SVN_ERR(svn_fs_fs__del_rep_reference(dst_fs, src_youngest, pool));
}
}
@@ -991,65 +995,33 @@ hotcopy_body(void *baton, apr_pool_t *po
SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path,
PATH_TXN_CURRENT, pool));
- return SVN_NO_ERROR;
-}
-
-/* Wrapper around hotcopy_body taking out all necessary source repository
- * locks.
- */
-static svn_error_t *
-hotcopy_locking_src_body(void *baton, apr_pool_t *pool)
-{
- struct hotcopy_body_baton *hbb = baton;
- fs_fs_data_t *src_ffd = hbb->src_fs->fsap_data;
+ /* Hotcopied FS is complete. Stamp it with a format file. */
+ SVN_ERR(svn_fs_fs__write_format(dst_fs, TRUE, pool));
- return src_ffd->format >= SVN_FS_FS__MIN_PACK_LOCK_FORMAT
- ? svn_error_trace(svn_fs_fs__with_pack_lock(hbb->src_fs, hotcopy_body,
- baton, pool))
- : hotcopy_body(baton, pool);
+ return SVN_NO_ERROR;
}
-/* Create an empty filesystem at DST_FS at DST_PATH with the same
- * configuration as SRC_FS (uuid, format, and other parameters).
- * After creation DST_FS has no revisions, not even revision zero. */
-static svn_error_t *
-hotcopy_create_empty_dest(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- const char *dst_path,
- apr_pool_t *pool)
+svn_error_t *
+svn_fs_fs__hotcopy(svn_fs_t *src_fs,
+ svn_fs_t *dst_fs,
+ const char *src_path,
+ const char *dst_path,
+ svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool)
{
- fs_fs_data_t *src_ffd = src_fs->fsap_data;
+ struct hotcopy_body_baton hbb;
- /* Create the DST_FS repository with the same layout as SRC_FS. */
- SVN_ERR(svn_fs_fs__create_file_tree(dst_fs, dst_path, src_ffd->format,
- src_ffd->max_files_per_dir,
- src_ffd->use_log_addressing,
- pool));
-
- /* Copy the UUID. Hotcopy destination receives a new instance ID, but
- * has the same filesystem UUID as the source. */
- SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, NULL, pool));
-
- /* Remove revision 0 contents. Otherwise, it may not get overwritten
- * due to having a newer timestamp. */
- SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_rev(dst_fs, 0, pool), pool));
- SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_revprops(dst_fs, 0, pool),
- pool));
-
- /* This filesystem is ready. Stamp it with a format number. Fail if
- * the 'format' file should already exist. */
- SVN_ERR(svn_fs_fs__write_format(dst_fs, FALSE, pool));
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
- return SVN_NO_ERROR;
-}
+ SVN_ERR(svn_fs_fs__open(src_fs, src_path, pool));
-svn_error_t *
-svn_fs_fs__hotcopy_prepare_target(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- const char *dst_path,
- svn_boolean_t incremental,
- apr_pool_t *pool)
-{
if (incremental)
{
const char *dst_format_abspath;
@@ -1061,39 +1033,51 @@ svn_fs_fs__hotcopy_prepare_target(svn_fs
SVN_ERR(svn_io_check_path(dst_format_abspath, &dst_format_kind, pool));
if (dst_format_kind == svn_node_none)
{
- /* Destination doesn't exist yet. Perform a normal hotcopy to a
- * empty destination using the same configuration as the source. */
- SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, pool));
- }
- else
- {
- /* Check the existing repository. */
- SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool));
- SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs,
- pool));
+ /* No destination? Fallback to a non-incremental hotcopy. */
+ incremental = FALSE;
}
}
+
+ if (incremental)
+ {
+ /* Check the existing repository. */
+ SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool));
+ SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs, pool));
+
+ SVN_ERR(svn_fs_fs__initialize_shared_data(dst_fs, common_pool_lock,
+ pool, common_pool));
+ SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
+ }
else
{
/* Start out with an empty destination using the same configuration
* as the source. */
- SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, pool));
+ fs_fs_data_t *src_ffd = src_fs->fsap_data;
+
+ /* Create the DST_FS repository with the same layout as SRC_FS. */
+ SVN_ERR(svn_fs_fs__create_file_tree(dst_fs, dst_path, src_ffd->format,
+ src_ffd->max_files_per_dir,
+ src_ffd->use_log_addressing,
+ pool));
+
+ /* Copy the UUID. Hotcopy destination receives a new instance ID, but
+ * has the same filesystem UUID as the source. */
+ SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, NULL, pool));
+
+ /* Remove revision 0 contents. Otherwise, it may not get overwritten
+ * due to having a newer timestamp. */
+ SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_rev(dst_fs, 0, pool),
+ pool));
+ SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_revprops(dst_fs, 0, pool),
+ pool));
+
+ SVN_ERR(svn_fs_fs__initialize_shared_data(dst_fs, common_pool_lock,
+ pool, common_pool));
+ SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
}
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_fs_fs__hotcopy(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- svn_boolean_t incremental,
- svn_fs_hotcopy_notify_t notify_func,
- void *notify_baton,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-{
- struct hotcopy_body_baton hbb;
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
hbb.src_fs = src_fs;
hbb.dst_fs = dst_fs;
@@ -1102,8 +1086,15 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs,
hbb.notify_baton = notify_baton;
hbb.cancel_func = cancel_func;
hbb.cancel_baton = cancel_baton;
- SVN_ERR(svn_fs_fs__with_all_locks(dst_fs, hotcopy_locking_src_body, &hbb,
- pool));
+
+ /* Lock the destination in the incremental mode. For a non-incremental
+ * hotcopy, don't take any locks. In that case the destination cannot be
+ * opened until the hotcopy finishes, and we don't have to worry about
+ * concurrency. */
+ if (incremental)
+ SVN_ERR(svn_fs_fs__with_all_locks(dst_fs, hotcopy_body, &hbb, pool));
+ else
+ SVN_ERR(hotcopy_body(&hbb, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.h
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.h?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.h (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/hotcopy.h Fri Sep 11 15:51:30 2015
@@ -25,27 +25,23 @@
#include "fs.h"
-/* Create an empty copy of the fsfs filesystem SRC_FS into a new DST_FS at
- * DST_PATH. If INCREMENTAL is TRUE, perform a few pre-checks only if
- * a repo already exists at DST_PATH. Use POOL for temporary allocations. */
-svn_error_t *
-svn_fs_fs__hotcopy_prepare_target(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- const char *dst_path,
- svn_boolean_t incremental,
- apr_pool_t *pool);
-
-/* Copy the fsfs filesystem SRC_FS into DST_FS. If INCREMENTAL is TRUE, do
- * not re-copy data which already exists in DST_FS. Indicate progress via
- * the optional NOTIFY_FUNC callback using NOTIFY_BATON. Use POOL for
- * temporary allocations. */
+/* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at
+ * DST_PATH. If INCREMENTAL is TRUE, do not re-copy data which already
+ * exists in DST_FS. Indicate progress via the optional NOTIFY_FUNC
+ * callback using NOTIFY_BATON. Use COMMON_POOL for process-wide and
+ * POOL for temporary allocations. Use COMMON_POOL_LOCK to ensure
+ * that the initialization of the shared data is serialized. */
svn_error_t * svn_fs_fs__hotcopy(svn_fs_t *src_fs,
svn_fs_t *dst_fs,
+ const char *src_path,
+ const char *dst_path,
svn_boolean_t incremental,
svn_fs_hotcopy_notify_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool);
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool);
#endif
Modified: subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/id.c?rev=1702504&r1=1702503&r2=1702504&view=diff
==============================================================================
--- subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/reuse-ra-session/subversion/libsvn_fs_fs/id.c Fri Sep 11 15:51:30 2015
@@ -610,7 +610,9 @@ svn_fs_fs__id_serialize(svn_temp_seriali
if (id == NULL)
return;
- /* serialize the id data struct itself */
+ /* Serialize the id data struct itself.
+ * Note that the structure behind IN is actually larger than a mere
+ * svn_fs_id_t . */
svn_temp_serializer__add_leaf(context,
(const void * const *)in,
sizeof(fs_fs__id_t));