You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2015/08/06 16:01:40 UTC

svn commit: r1694500 [3/7] - in /subversion/branches/fsx-1.10: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ subversion/bindings/ctypes-python/csvn/ext/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apac...

Modified: subversion/branches/fsx-1.10/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_client/resolved.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_client/resolved.c Thu Aug  6 14:01:38 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,64 +151,970 @@ 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;
+  
+} conflict_walk_baton_t;
+
+/* 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_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_kind(const svn_client_conflict_t *conflict)
 {
-  return conflict->kind;
+  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 conflict->reason;
+  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_wc_conflict_description2_t *conflict,
-  apr_pool_t *result_pool,
-  apr_pool_t *scratch_pool)
+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)
 {
   if (repos_root_url)
     {
-      if (conflict->src_left_version)
-        *repos_root_url = conflict->src_left_version->repos_url;
-      else if (conflict->src_right_version)
-        *repos_root_url = conflict->src_right_version->repos_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 (conflict->src_left_version)
-        *repos_uuid = conflict->src_left_version->repos_uuid;
-      else if (conflict->src_right_version)
-        *repos_uuid = conflict->src_right_version->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;
     }
@@ -218,30 +1127,33 @@ svn_client_conflict_get_incoming_old_rep
   const char **incoming_old_repos_relpath,
   svn_revnum_t *incoming_old_pegrev,
   svn_node_kind_t *incoming_old_node_kind,
-  const svn_wc_conflict_description2_t *conflict,
+  const svn_client_conflict_t *conflict,
   apr_pool_t *result_pool,
   apr_pool_t *scratch_pool)
 {
   if (incoming_old_repos_relpath)
     {
-      if (conflict->src_left_version)
-        *incoming_old_repos_relpath = conflict->src_left_version->path_in_repos;
+      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 (conflict->src_left_version)
-        *incoming_old_pegrev = conflict->src_left_version->peg_rev;
+      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 (conflict->src_left_version)
-        *incoming_old_node_kind = conflict->src_left_version->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;
     }
@@ -254,31 +1166,33 @@ svn_client_conflict_get_incoming_new_rep
   const char **incoming_new_repos_relpath,
   svn_revnum_t *incoming_new_pegrev,
   svn_node_kind_t *incoming_new_node_kind,
-  const svn_wc_conflict_description2_t *conflict,
+  const svn_client_conflict_t *conflict,
   apr_pool_t *result_pool,
   apr_pool_t *scratch_pool)
 {
   if (incoming_new_repos_relpath)
     {
-      if (conflict->src_right_version)
+      if (get_conflict_desc2_t(conflict)->src_right_version)
         *incoming_new_repos_relpath =
-          conflict->src_right_version->path_in_repos;
+          get_conflict_desc2_t(conflict)->src_right_version->path_in_repos;
       else
         *incoming_new_repos_relpath = NULL;
     }
 
   if (incoming_new_pegrev)
     {
-      if (conflict->src_right_version)
-        *incoming_new_pegrev = conflict->src_right_version->peg_rev;
+      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 (conflict->src_right_version)
-        *incoming_new_node_kind = conflict->src_right_version->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;
     }
@@ -288,73 +1202,85 @@ svn_client_conflict_get_incoming_new_rep
 
 svn_node_kind_t
 svn_client_conflict_tree_get_victim_node_kind(
-  const svn_wc_conflict_description2_t *conflict)
+  const svn_client_conflict_t *conflict)
 {
   SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
       == svn_wc_conflict_kind_tree);
 
-  return conflict->node_kind;
+  return get_conflict_desc2_t(conflict)->node_kind;
 }
 
 const char *
-svn_client_conflict_prop_get_propname(
-  const svn_wc_conflict_description2_t *conflict)
+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 conflict->property_name;
+  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_wc_conflict_description2_t *conflict,
+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(conflict->prop_value_base, result_pool);
+    *base_propval =
+      svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_base,
+                     result_pool);
 
   if (working_propval)
-    *working_propval = svn_string_dup(conflict->prop_value_working,
-                                      result_pool);
+    *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(conflict->prop_value_incoming_old,
-                                           result_pool);
+    *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(conflict->prop_value_incoming_new,
-                                           result_pool);
+    *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_text_get_mime_type(
-  const svn_wc_conflict_description2_t *conflict)
+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 conflict->mime_type;
+  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_wc_conflict_description2_t *conflict,
-  apr_pool_t *result_pool,
-  apr_pool_t *scratch_pool)
+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);
@@ -365,17 +1291,17 @@ svn_client_conflict_text_get_contents(
           svn_wc_operation_merge)
         *base_abspath = NULL; /* ### WC base contents not available yet */
       else /* update/switch */
-        *base_abspath = conflict->base_abspath;
+        *base_abspath = get_conflict_desc2_t(conflict)->base_abspath;
     }
 
   if (working_abspath)
-    *working_abspath = conflict->my_abspath;
+    *working_abspath = get_conflict_desc2_t(conflict)->my_abspath;
 
   if (incoming_old_abspath)
-    *incoming_old_abspath = conflict->base_abspath;
+    *incoming_old_abspath = get_conflict_desc2_t(conflict)->base_abspath;
 
   if (incoming_new_abspath)
-    *incoming_new_abspath = conflict->their_abspath;
+    *incoming_new_abspath = get_conflict_desc2_t(conflict)->their_abspath;
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_diff/parse-diff.c Thu Aug  6 14:01:38 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/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_base/revs-txns.c Thu Aug  6 14:01:38 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/fsx-1.10/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/caching.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/caching.c Thu Aug  6 14:01:38 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/fsx-1.10/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/fs_fs.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/fs_fs.c Thu Aug  6 14:01:38 2015
@@ -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/fsx-1.10/subversion/libsvn_fs_fs/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/pack.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/pack.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/pack.c Thu Aug  6 14:01:38 2015
@@ -1987,7 +1987,14 @@ pack_body(void *baton,
      we need to re-read the pack status. */
   SVN_ERR(get_pack_status(&fully_packed, pb->fs, pool));
   if (fully_packed)
-    return SVN_NO_ERROR;
+    {
+      if (pb->notify_func)
+        (*pb->notify_func)(pb->notify_baton,
+                           ffd->min_unpacked_rev / ffd->max_files_per_dir,
+                           svn_fs_pack_notify_noop, pool);
+
+      return SVN_NO_ERROR;
+    }
 
   completed_shards = (ffd->youngest_rev_cache + 1) / ffd->max_files_per_dir;
   pb->revs_dir = svn_dirent_join(pb->fs->path, PATH_REVS_DIR, pool);
@@ -2034,12 +2041,24 @@ svn_fs_fs__pack(svn_fs_t *fs,
 
   /* If we aren't using sharding, we can't do any packing, so quit. */
   if (!ffd->max_files_per_dir)
-    return SVN_NO_ERROR;
+    {
+      if (notify_func)
+        (*notify_func)(notify_baton, -1, svn_fs_pack_notify_noop, pool);
+
+      return SVN_NO_ERROR;
+    }
 
   /* Is there we even anything to do?. */
   SVN_ERR(get_pack_status(&fully_packed, fs, pool));
   if (fully_packed)
-    return SVN_NO_ERROR;
+    {
+      if (notify_func)
+        (*notify_func)(notify_baton,
+                       ffd->min_unpacked_rev / ffd->max_files_per_dir,
+                       svn_fs_pack_notify_noop, pool);
+
+      return SVN_NO_ERROR;
+    }
 
   /* Lock the repo and start the pack process. */
   pb.fs = fs;

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c Thu Aug  6 14:01:38 2015
@@ -1153,19 +1153,22 @@ set_txn_proplist(svn_fs_t *fs,
                  apr_hash_t *props,
                  apr_pool_t *pool)
 {
-  svn_stringbuf_t *buf;
-  svn_stream_t *stream;
+  svn_stream_t *tmp_stream;
+  const char *tmp_path;
+  const char *final_path = path_txn_props(fs, txn_id, pool);
 
-  /* Write out the new file contents to BUF. */
-  buf = svn_stringbuf_create_ensure(1024, pool);
-  stream = svn_stream_from_stringbuf(buf, pool);
-  SVN_ERR(svn_hash_write2(props, stream, SVN_HASH_TERMINATOR, pool));
-  SVN_ERR(svn_stream_close(stream));
+  /* Write the new contents into a temporary file. */
+  SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_path,
+                                 svn_dirent_dirname(final_path, pool),
+                                 svn_io_file_del_none,
+                                 pool, pool));
+
+  /* Replace the old file with the new one. */
+  SVN_ERR(svn_hash_write2(props, tmp_stream, SVN_HASH_TERMINATOR, pool));
+  SVN_ERR(svn_stream_close(tmp_stream));
+
+  SVN_ERR(svn_io_file_rename(tmp_path, final_path, pool));
 
-  /* Open the transaction properties file and write new contents to it. */
-  SVN_ERR(svn_io_write_atomic(path_txn_props(fs, txn_id, pool),
-                              buf->data, buf->len,
-                              NULL /* copy_perms_path */, pool));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c Thu Aug  6 14:01:38 2015
@@ -816,8 +816,15 @@ verify_f7_metadata_consistency(svn_fs_t
       /* concurrent packing is one of the reasons why verification may fail.
          Make sure, we operate on up-to-date information. */
       if (err)
-        SVN_ERR(svn_fs_fs__read_min_unpacked_rev(&ffd->min_unpacked_rev,
-                                                 fs, pool));
+        {
+          svn_error_t *err2
+            = svn_fs_fs__read_min_unpacked_rev(&ffd->min_unpacked_rev,
+                                               fs, pool);
+
+          /* Be careful to not leak ERR. */
+          if (err2)
+            return svn_error_trace(svn_error_compose_create(err, err2));
+        }
 
       /* retry the whole shard if it got packed in the meantime */
       if (err && count != pack_size(fs, revision))

Propchange: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Aug  6 14:01:38 2015
@@ -1,3 +1,4 @@
+/subversion/branches/1.10-cache-improvements/subversion/libsvn_fs_x:1669168-1694487
 /subversion/branches/1.5.x-r30215/subversion/libsvn_fs_x:870312
 /subversion/branches/1.7.x-fs-verify/subversion/libsvn_fs_x:1146708,1161180
 /subversion/branches/10Gb/subversion/libsvn_fs_x:1388102,1388163-1388190,1388195,1388202,1388205,1388211,1388276,1388362,1388375,1388394,1388636,1388639-1388640,1388643-1388644,1388654,1388720,1388789,1388795,1388801,1388805,1388807,1388810,1388816,1389044,1389276,1389289,1389662,1389867,1390017,1390209,1390216,1390407,1390409,1390414,1390419,1390955
@@ -90,4 +91,4 @@
 /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110
 /subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384
 /subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1653608,
 1658482
-/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1658218-1685462
+/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1658218-1694490

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c Thu Aug  6 14:01:38 2015
@@ -1030,22 +1030,14 @@ get_cached_window_sizes(window_sizes_t *
                         svn_boolean_t *is_cached,
                         apr_pool_t *pool)
 {
-  if (! rs->window_cache)
-    {
-      /* txdelta window has not been enabled */
-      *is_cached = FALSE;
-    }
-  else
-    {
-      svn_fs_x__window_cache_key_t key = { 0 };
-      SVN_ERR(svn_cache__get_partial((void **)sizes,
-                                     is_cached,
-                                     rs->window_cache,
-                                     get_window_key(&key, rs),
-                                     get_cached_window_sizes_func,
-                                     NULL,
-                                     pool));
-    }
+  svn_fs_x__window_cache_key_t key = { 0 };
+  SVN_ERR(svn_cache__get_partial((void **)sizes,
+                                 is_cached,
+                                 rs->window_cache,
+                                 get_window_key(&key, rs),
+                                 get_cached_window_sizes_func,
+                                 NULL,
+                                 pool));
 
   return SVN_NO_ERROR;
 }
@@ -1058,33 +1050,25 @@ get_cached_window(svn_txdelta_window_t *
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
-  if (! rs->window_cache)
-    {
-      /* txdelta window has not been enabled */
-      *is_cached = FALSE;
-    }
-  else
-    {
-      /* ask the cache for the desired txdelta window */
-      svn_fs_x__txdelta_cached_window_t *cached_window;
-      svn_fs_x__window_cache_key_t key = { 0 };
-      get_window_key(&key, rs);
-      key.chunk_index = chunk_index;
-      SVN_ERR(svn_cache__get((void **) &cached_window,
-                             is_cached,
-                             rs->window_cache,
-                             &key,
-                             result_pool));
-
-      if (*is_cached)
-        {
-          /* found it. Pass it back to the caller. */
-          *window_p = cached_window->window;
-
-          /* manipulate the RS as if we just read the data */
-          rs->current = cached_window->end_offset;
-          rs->chunk_index = chunk_index;
-        }
+  /* ask the cache for the desired txdelta window */
+  svn_fs_x__txdelta_cached_window_t *cached_window;
+  svn_fs_x__window_cache_key_t key = { 0 };
+  get_window_key(&key, rs);
+  key.chunk_index = chunk_index;
+  SVN_ERR(svn_cache__get((void **) &cached_window,
+                         is_cached,
+                         rs->window_cache,
+                         &key,
+                         result_pool));
+
+  if (*is_cached)
+    {
+      /* found it. Pass it back to the caller. */
+      *window_p = cached_window->window;
+
+      /* manipulate the RS as if we just read the data */
+      rs->current = cached_window->end_offset;
+      rs->chunk_index = chunk_index;
     }
 
   return SVN_NO_ERROR;
@@ -1100,23 +1084,20 @@ set_cached_window(svn_txdelta_window_t *
                   apr_off_t start_offset,
                   apr_pool_t *scratch_pool)
 {
-  if (rs->window_cache)
-    {
-      /* store the window and the first offset _past_ it */
-      svn_fs_x__txdelta_cached_window_t cached_window;
-      svn_fs_x__window_cache_key_t key = {0};
-
-      cached_window.window = window;
-      cached_window.start_offset = start_offset - rs->start;
-      cached_window.end_offset = rs->current;
-
-      /* but key it with the start offset because that is the known state
-       * when we will look it up */
-      SVN_ERR(svn_cache__set(rs->window_cache,
-                             get_window_key(&key, rs),
-                             &cached_window,
-                             scratch_pool));
-    }
+  /* store the window and the first offset _past_ it */
+  svn_fs_x__txdelta_cached_window_t cached_window;
+  svn_fs_x__window_cache_key_t key = {0};
+
+  cached_window.window = window;
+  cached_window.start_offset = start_offset - rs->start;
+  cached_window.end_offset = rs->current;
+
+  /* but key it with the start offset because that is the known state
+   * when we will look it up */
+  SVN_ERR(svn_cache__set(rs->window_cache,
+                         get_window_key(&key, rs),
+                         &cached_window,
+                         scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1133,23 +1114,13 @@ get_cached_combined_window(svn_stringbuf
                            svn_boolean_t *is_cached,
                            apr_pool_t *pool)
 {
-  if (! rs->combined_cache)
-    {
-      /* txdelta window has not been enabled */
-      *is_cached = FALSE;
-    }
-  else
-    {
-      /* ask the cache for the desired txdelta window */
-      svn_fs_x__window_cache_key_t key = { 0 };
-      return svn_cache__get((void **)window_p,
-                            is_cached,
-                            rs->combined_cache,
-                            get_window_key(&key, rs),
-                            pool);
-    }
-
-  return SVN_NO_ERROR;
+  /* ask the cache for the desired txdelta window */
+  svn_fs_x__window_cache_key_t key = { 0 };
+  return svn_cache__get((void **)window_p,
+                        is_cached,
+                        rs->combined_cache,
+                        get_window_key(&key, rs),
+                        pool);
 }
 
 /* Store the WINDOW read for the rep state RS in the current FSX session's
@@ -1160,18 +1131,13 @@ set_cached_combined_window(svn_stringbuf
                            rep_state_t *rs,
                            apr_pool_t *scratch_pool)
 {
-  if (rs->combined_cache)
-    {
-      /* but key it with the start offset because that is the known state
-       * when we will look it up */
-      svn_fs_x__window_cache_key_t key = { 0 };
-      return svn_cache__set(rs->combined_cache,
-                            get_window_key(&key, rs),
-                            window,
-                            scratch_pool);
-    }
-
-  return SVN_NO_ERROR;
+  /* but key it with the start offset because that is the known state
+   * when we will look it up */
+  svn_fs_x__window_cache_key_t key = { 0 };
+  return svn_cache__set(rs->combined_cache,
+                        get_window_key(&key, rs),
+                        window,
+                        scratch_pool);
 }
 
 /* Build an array of rep_state structures in *LIST giving the delta
@@ -1701,13 +1667,12 @@ read_rep_header(svn_fs_x__rep_header_t *
   svn_boolean_t is_cached = FALSE;
 
   SVN_ERR(svn_cache__get((void**)rep_header, &is_cached,
-                          ffd->rep_header_cache, key, pool));
+                         ffd->rep_header_cache, key, pool));
   if (is_cached)
     return SVN_NO_ERROR;
 
   SVN_ERR(svn_fs_x__rev_file_stream(&stream, file));
   SVN_ERR(svn_fs_x__read_rep_header(rep_header, stream, pool, pool));
-
   SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header, pool));
 
   return SVN_NO_ERROR;
@@ -2140,7 +2105,7 @@ svn_fs_x__get_contents(svn_stream_t **co
       /* Make the stream attempt fulltext cache lookups if the fulltext
        * is cacheable.  If it is not, then also don't try to buffer and
        * cache it. */
-      if (ffd->fulltext_cache && cache_fulltext
+      if (   cache_fulltext
           && SVN_IS_VALID_REVNUM(revision)
           && fulltext_size_is_cachable(ffd, len))
         {
@@ -2211,8 +2176,7 @@ svn_fs_x__try_process_file_contents(svn_
 
       fulltext_cache_key.revision = svn_fs_x__get_revnum(rep->id.change_set);
       fulltext_cache_key.second = rep->id.number;
-      if (ffd->fulltext_cache
-          && SVN_IS_VALID_REVNUM(fulltext_cache_key.revision)
+      if (   SVN_IS_VALID_REVNUM(fulltext_cache_key.revision)
           && fulltext_size_is_cachable(ffd, rep->expanded_size))
         {
           cache_access_wrapper_baton_t wrapper_baton;
@@ -2298,12 +2262,11 @@ svn_fs_x__get_file_delta_stream(svn_txde
   svn_stream_t *source_stream, *target_stream;
   rep_state_t *rep_state;
   svn_fs_x__rep_header_t *rep_header;
-  svn_fs_x__data_t *ffd = fs->fsap_data;
 
   /* Try a shortcut: if the target is stored as a delta against the source,
      then just use that delta.  However, prefer using the fulltext cache
      whenever that is available. */
-  if (target->data_rep && (source || !ffd->fulltext_cache))
+  if (target->data_rep && source)
     {
       /* Read target's base rep if any. */
       SVN_ERR(create_rep_state(&rep_state, &rep_header, NULL,
@@ -2608,23 +2571,19 @@ svn_fs_x__rep_contents_dir(apr_array_hea
 
   /* find the cache we may use */
   svn_cache__t *cache = locate_dir_cache(fs, &key, noderev);
-  if (cache)
-    {
-      svn_boolean_t found;
+  svn_boolean_t found;
 
-      SVN_ERR(svn_cache__get((void **)entries_p, &found, cache, &key,
-                             result_pool));
-      if (found)
-        return SVN_NO_ERROR;
-    }
+  SVN_ERR(svn_cache__get((void **)entries_p, &found, cache, &key,
+                         result_pool));
+  if (found)
+    return SVN_NO_ERROR;
 
   /* Read in the directory contents. */
   SVN_ERR(get_dir_contents(entries_p, fs, noderev, result_pool,
                            scratch_pool));
 
   /* Update the cache, if we are to use one. */
-  if (cache)
-    SVN_ERR(svn_cache__set(cache, &key, *entries_p, scratch_pool));
+  SVN_ERR(svn_cache__set(cache, &key, *entries_p, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -2653,25 +2612,22 @@ svn_fs_x__rep_contents_dir_entry(svn_fs_
   /* find the cache we may use */
   svn_fs_x__id_t key;
   svn_cache__t *cache = locate_dir_cache(fs, &key, noderev);
-  if (cache)
-    {
-      svn_fs_x__ede_baton_t baton;
-      baton.hint = *hint;
-      baton.name = name;
-
-      /* Cache lookup. */
-      SVN_ERR(svn_cache__get_partial((void **)dirent,
-                                     &found,
-                                     cache,
-                                     &key,
-                                     svn_fs_x__extract_dir_entry,
-                                     &baton,
-                                     result_pool));
-
-      /* Remember the new clue only if we found something at that spot. */
-      if (found)
-        *hint = baton.hint;
-    }
+  svn_fs_x__ede_baton_t baton;
+  baton.hint = *hint;
+  baton.name = name;
+
+  /* Cache lookup. */
+  SVN_ERR(svn_cache__get_partial((void **)dirent,
+                                 &found,
+                                 cache,
+                                 &key,
+                                 svn_fs_x__extract_dir_entry,
+                                 &baton,
+                                 result_pool));
+
+  /* Remember the new clue only if we found something at that spot. */
+  if (found)
+    *hint = baton.hint;
 
   /* fetch data from disk if we did not find it in the cache */
   if (! found)
@@ -2732,7 +2688,7 @@ svn_fs_x__get_proplist(apr_hash_t **prop
 
       key.revision = svn_fs_x__get_revnum(rep->id.change_set);
       key.second = rep->id.number;
-      if (ffd->properties_cache && SVN_IS_VALID_REVNUM(key.revision))
+      if (SVN_IS_VALID_REVNUM(key.revision))
         {
           svn_boolean_t is_cached;
           SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
@@ -2748,7 +2704,7 @@ svn_fs_x__get_proplist(apr_hash_t **prop
                              result_pool));
       SVN_ERR(svn_stream_close(stream));
 
-      if (ffd->properties_cache && SVN_IS_VALID_REVNUM(rep->id.change_set))
+      if (SVN_IS_VALID_REVNUM(rep->id.change_set))
         SVN_ERR(svn_cache__set(ffd->properties_cache, &key, proplist,
                                scratch_pool));
     }
@@ -2839,15 +2795,11 @@ block_read_contents(svn_fs_t *fs,
                     apr_off_t max_offset,
                     apr_pool_t *scratch_pool)
 {
-  svn_fs_x__data_t *ffd = fs->fsap_data;
   svn_fs_x__representation_cache_key_t header_key = { 0 };
   rep_state_t rs = { 0 };
   svn_filesize_t fulltext_len;
   svn_fs_x__rep_header_t *rep_header;
 
-  if (!ffd->txdelta_window_cache || !ffd->combined_window_cache)
-    return SVN_NO_ERROR;
-
   header_key.revision = (apr_int32_t)key->revision;
   header_key.is_packed = svn_fs_x__is_packed_rev(fs, header_key.revision);
   header_key.item_index = key->second;
@@ -2924,6 +2876,7 @@ block_read_changes(apr_array_header_t **
   svn_fs_x__data_t *ffd = fs->fsap_data;
   svn_stream_t *stream;
   svn_revnum_t revision = svn_fs_x__get_revnum(entry->items[0].change_set);
+  apr_size_t estimated_size;
 
   /* we don't support containers, yet */
   SVN_ERR_ASSERT(entry->item_count == 1);
@@ -2941,24 +2894,20 @@ block_read_changes(apr_array_header_t **
   SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read changes from revision file */
-
   SVN_ERR(svn_fs_x__read_changes(changes, stream, result_pool, scratch_pool));
 
   /* cache for future reference */
 
-  if (ffd->changes_cache)
-    {
-      /* Guesstimate for the size of the in-cache representation. */
-      apr_size_t estimated_size = (apr_size_t)250 * (*changes)->nelts;
+  /* Guesstimate for the size of the in-cache representation. */
+  estimated_size = (apr_size_t)250 * (*changes)->nelts;
 
-      /* Don't even serialize data that probably won't fit into the
-        * cache.  This often implies that either CHANGES is very
-        * large, memory is scarce or both.  Having a huge temporary
-        * copy would not be a good thing in either case. */
-      if (svn_cache__is_cachable(ffd->changes_cache, estimated_size))
-        SVN_ERR(svn_cache__set(ffd->changes_cache, &revision, *changes,
-                               scratch_pool));
-    }
+  /* Don't even serialize data that probably won't fit into the
+   * cache.  This often implies that either CHANGES is very
+   * large, memory is scarce or both.  Having a huge temporary
+   * copy would not be a good thing in either case. */
+  if (svn_cache__is_cachable(ffd->changes_cache, estimated_size))
+    SVN_ERR(svn_cache__set(ffd->changes_cache, &revision, *changes,
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -3004,7 +2953,6 @@ block_read_changes_container(apr_array_h
   if (must_read)
     SVN_ERR(svn_fs_x__changes_get_list(changes, container, sub_item,
                                        result_pool));
-
   SVN_ERR(svn_cache__set(ffd->changes_container_cache, &key, container,
                          scratch_pool));