You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pr...@apache.org on 2013/04/05 07:29:34 UTC

svn commit: r1464833 [4/11] - in /subversion/branches/verify-keep-going: ./ build/ build/generator/ contrib/client-side/svncopy/ notes/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/...

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/merge.c Fri Apr  5 05:29:29 2013
@@ -2002,9 +2002,14 @@ merge_file_changed(const char *relpath,
                                   left, right,
                                   left_props, prop_changes,
                                   merge_b->dry_run,
-                                  ctx->conflict_func2, ctx->conflict_baton2,
+                                  NULL, NULL,
                                   ctx->cancel_func, ctx->cancel_baton,
                                   scratch_pool));
+      if (property_state == svn_wc_notify_state_conflicted)
+        {
+          alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
+                               merge_b->pool);
+        }
     }
 
   /* Easy out: We are only applying mergeinfo differences. */
@@ -2040,7 +2045,7 @@ merge_file_changed(const char *relpath,
                             merge_b->dry_run, merge_b->diff3_cmd,
                             merge_b->merge_options,
                             left_props, prop_changes,
-                            ctx->conflict_func2, ctx->conflict_baton2,
+                            NULL, NULL,
                             ctx->cancel_func,
                             ctx->cancel_baton,
                             scratch_pool));
@@ -2842,7 +2847,7 @@ merge_dir_changed(const char *relpath,
                                   left, right,
                                   left_props, props,
                                   merge_b->dry_run,
-                                  ctx->conflict_func2, ctx->conflict_baton2,
+                                  NULL, NULL,
                                   ctx->cancel_func, ctx->cancel_baton,
                                   scratch_pool));
 
@@ -2994,11 +2999,15 @@ merge_dir_added(const char *relpath,
                                   svn_prop_hash_to_array(new_props,
                                                          scratch_pool),
                                   merge_b->dry_run,
-                                  merge_b->ctx->conflict_func2,
-                                  merge_b->ctx->conflict_baton2,
+                                  NULL, NULL,
                                   merge_b->ctx->cancel_func,
                                   merge_b->ctx->cancel_baton,
                                   scratch_pool));
+      if (prop_state == svn_wc_notify_state_conflicted)
+        {
+          alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
+                               merge_b->pool);
+        }
     }
 
   return SVN_NO_ERROR;
@@ -5319,6 +5328,38 @@ record_skips_in_mergeinfo(const char *me
 }
 
 /* Data for reporting when a merge aborted because of raising conflicts.
+ */
+typedef struct single_range_conflict_report_t
+{
+  /* What sub-range of the requested source raised conflicts?
+   * The 'inheritable' flag is ignored. */
+  merge_source_t *conflicted_range;
+  /* What sub-range of the requested source remains to be merged?
+   * NULL if no more.  The 'inheritable' flag is ignored. */
+  merge_source_t *remaining_source;
+
+} single_range_conflict_report_t;
+
+/* Create a single_range_conflict_report_t, containing deep copies of
+ * CONFLICTED_RANGE and REMAINING_SOURCE, allocated in RESULT_POOL. */
+static single_range_conflict_report_t *
+single_range_conflict_report_create(const merge_source_t *conflicted_range,
+                                    const merge_source_t *remaining_source,
+                                    apr_pool_t *result_pool)
+{
+  single_range_conflict_report_t *report
+    = apr_palloc(result_pool, sizeof(*report));
+
+  assert(conflicted_range != NULL);
+
+  report->conflicted_range = merge_source_dup(conflicted_range, result_pool);
+  report->remaining_source
+    = remaining_source ? merge_source_dup(remaining_source, result_pool)
+                       : NULL;
+  return report;
+}
+
+/* Data for reporting when a merge aborted because of raising conflicts.
  *
  * ### TODO: More info, including the ranges (or other parameters) the user
  *     needs to complete the merge.
@@ -5327,7 +5368,8 @@ typedef struct conflict_report_t
 {
   const char *target_abspath;
   /* The revision range during which conflicts were raised */
-  svn_merge_range_t *r;
+  const merge_source_t *conflicted_range;
+  /* Was the conflicted range the last range in the whole requested merge? */
   svn_boolean_t was_last_range;
 } conflict_report_t;
 
@@ -5335,14 +5377,14 @@ typedef struct conflict_report_t
  * allocated in RESULT_POOL. */
 static conflict_report_t *
 conflict_report_create(const char *target_abspath,
-                       const svn_merge_range_t *conflicted_range,
+                       const merge_source_t *conflicted_range,
                        svn_boolean_t was_last_range,
                        apr_pool_t *result_pool)
 {
   conflict_report_t *report = apr_palloc(result_pool, sizeof(*report));
 
   report->target_abspath = apr_pstrdup(result_pool, target_abspath);
-  report->r = svn_merge_range_dup(conflicted_range, result_pool);
+  report->conflicted_range = merge_source_dup(conflicted_range, result_pool);
   report->was_last_range = was_last_range;
   return report;
 }
@@ -5355,7 +5397,8 @@ conflict_report_dup(const conflict_repor
   conflict_report_t *new = apr_pmemdup(result_pool, report, sizeof(*new));
 
   new->target_abspath = apr_pstrdup(result_pool, report->target_abspath);
-  new->r = svn_merge_range_dup(report->r, result_pool);
+  new->conflicted_range = merge_source_dup(report->conflicted_range,
+                                           result_pool);
   return new;
 }
 
@@ -5368,13 +5411,17 @@ make_merge_conflict_error(conflict_repor
   assert(!report || svn_dirent_is_absolute(report->target_abspath));
 
   if (report && ! report->was_last_range)
-    return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
+    {
+      svn_error_t *err = svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
        _("One or more conflicts were produced while merging r%ld:%ld into\n"
          "'%s' --\n"
          "resolve all conflicts and rerun the merge to apply the remaining\n"
          "unmerged revisions"),
-       report->r->start, report->r->end,
+       report->conflicted_range->loc1->rev, report->conflicted_range->loc2->rev,
        svn_dirent_local_style(report->target_abspath, scratch_pool));
+      assert(report->conflicted_range->loc1->rev != report->conflicted_range->loc2->rev); /* ### is a valid case in a 2-URL merge */
+      return err;
+    }
   return SVN_NO_ERROR;
 }
 
@@ -7237,6 +7284,7 @@ subrange_source(const merge_source_t *so
 
   /* For this function we require that the input source is 'ancestral'. */
   SVN_ERR_ASSERT_NO_RETURN(source->ancestral);
+  SVN_ERR_ASSERT_NO_RETURN(start_rev != end_rev);
 
   loc1.rev = start_rev;
   loc2.rev = end_rev;
@@ -7277,7 +7325,7 @@ subrange_source(const merge_source_t *so
 */
 static svn_error_t *
 do_file_merge(svn_mergeinfo_catalog_t result_catalog,
-              svn_merge_range_t **conflicted_range,
+              single_range_conflict_report_t **conflict_report,
               const merge_source_t *source,
               const char *target_abspath,
               const svn_diff_tree_processor_t *processor,
@@ -7301,7 +7349,7 @@ do_file_merge(svn_mergeinfo_catalog_t re
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
 
-  *conflicted_range = NULL;
+  *conflict_report = NULL;
 
   /* Note that this is a single-file merge. */
   range.start = source->loc1->rev;
@@ -7352,6 +7400,26 @@ do_file_merge(svn_mergeinfo_catalog_t re
                                              ctx, scratch_pool,
                                              iterpool));
           remaining_ranges = merge_target->remaining_ranges;
+
+          /* We are honoring mergeinfo and this is not a simple record only
+             merge which blindly records mergeinfo describing the merge of
+             SOURCE->LOC1->URL@SOURCE->LOC1->REV through
+             SOURCE->LOC2->URL@SOURCE->LOC2->REV.  This means that the oldest
+             and youngest revisions merged (as determined above by
+             calculate_remaining_ranges) might differ from those described
+             in SOURCE.  To keep the '--- Merging *' notifications consistent
+             with the '--- Recording mergeinfo *' notifications, we adjust
+             RANGE to account for such changes. */
+          if (remaining_ranges->nelts)
+            {
+              svn_merge_range_t *adj_start_range =
+                APR_ARRAY_IDX(remaining_ranges, 0, svn_merge_range_t *);
+              svn_merge_range_t *adj_end_range =
+                APR_ARRAY_IDX(remaining_ranges, remaining_ranges->nelts - 1,
+                              svn_merge_range_t *);
+              range.start = adj_start_range->start;
+              range.end = adj_end_range->end;
+            }
         }
     }
 
@@ -7545,7 +7613,16 @@ do_file_merge(svn_mergeinfo_catalog_t re
 
           if (is_path_conflicted_by_merge(merge_b))
             {
-              *conflicted_range = svn_merge_range_dup(r, result_pool);
+              merge_source_t *remaining_range = NULL;
+
+              if (real_source->loc2->rev != source->loc2->rev)
+                remaining_range = subrange_source(source,
+                                                  real_source->loc2->rev,
+                                                  source->loc2->rev,
+                                                  scratch_pool);
+              *conflict_report = single_range_conflict_report_create(
+                                   real_source, remaining_range, result_pool);
+
               /* Only record partial mergeinfo if only a partial merge was
                  performed before a conflict was encountered. */
               range.end = r->end;
@@ -7802,14 +7879,14 @@ subtree_touched_by_merge(const char *loc
    SOURCE, DEPTH, NOTIFY_B, and MERGE_B
    are all cascaded from do_directory_merge's arguments of the same names.
 
-   CONFLICTED_RANGE is as documented for do_directory_merge().
+   CONFLICT_REPORT is as documented for do_directory_merge().
 
    NOTE: This is a very thin wrapper around drive_merge_report_editor() and
    exists only to populate CHILDREN_WITH_MERGEINFO with the single element
    expected during mergeinfo unaware merges.
 */
 static svn_error_t *
-do_mergeinfo_unaware_dir_merge(svn_merge_range_t **conflicted_range,
+do_mergeinfo_unaware_dir_merge(single_range_conflict_report_t **conflict_report,
                                const merge_source_t *source,
                                const char *target_dir_wcpath,
                                apr_array_header_t *children_with_mergeinfo,
@@ -7825,7 +7902,7 @@ do_mergeinfo_unaware_dir_merge(svn_merge
   svn_client__merge_path_t *item
     = svn_client__merge_path_create(target_dir_wcpath, scratch_pool);
 
-  *conflicted_range = NULL;
+  *conflict_report = NULL;
   item->remaining_ranges = svn_rangelist__initialize(source->loc1->rev,
                                                      source->loc2->rev,
                                                      TRUE, scratch_pool);
@@ -7837,11 +7914,8 @@ do_mergeinfo_unaware_dir_merge(svn_merge
                                     merge_b, scratch_pool));
   if (is_path_conflicted_by_merge(merge_b))
     {
-      svn_merge_range_t *r = apr_palloc(result_pool, sizeof(*r));
-      r->start = source->loc1->rev;
-      r->end = source->loc2->rev;
-      r->inheritable = TRUE;
-      *conflicted_range = r;
+      *conflict_report = single_range_conflict_report_create(
+                           source, NULL, result_pool);
     }
   return SVN_NO_ERROR;
 }
@@ -9088,7 +9162,7 @@ remove_noop_subtree_ranges(const merge_s
 
    Handle DEPTH as documented for svn_client_merge5().
 
-   CONFLICTED_RANGE is as documented for do_directory_merge().
+   CONFLICT_REPORT is as documented for do_directory_merge().
 
    Perform any temporary allocations in SCRATCH_POOL.
 
@@ -9099,7 +9173,7 @@ remove_noop_subtree_ranges(const merge_s
 */
 static svn_error_t *
 do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
-                             svn_merge_range_t **conflicted_range,
+                             single_range_conflict_report_t **conflict_report,
                              const merge_source_t *source,
                              const char *target_abspath,
                              apr_array_header_t *children_with_mergeinfo,
@@ -9131,7 +9205,7 @@ do_mergeinfo_aware_dir_merge(svn_mergein
        same repository as the target -- merge tracking might be
        happenin'! ***/
 
-  *conflicted_range = NULL;
+  *conflict_report = NULL;
 
   /* Point our RA_SESSION to the URL of our youngest merge source side. */
   ra_session = is_rollback ? merge_b->ra_session1 : merge_b->ra_session2;
@@ -9320,11 +9394,17 @@ do_mergeinfo_aware_dir_merge(svn_mergein
                  we have merged. */
               if (is_path_conflicted_by_merge(merge_b))
                 {
-                  svn_merge_range_t *r = apr_palloc(result_pool, sizeof(*r));
-                  r->start = start_rev;
-                  r->end = end_rev;
-                  r->inheritable = TRUE;
-                  *conflicted_range = r;
+                  merge_source_t *remaining_range = NULL;
+
+                  if (real_source->loc2->rev != source->loc2->rev)
+                    remaining_range = subrange_source(source,
+                                                      real_source->loc2->rev,
+                                                      source->loc2->rev,
+                                                      scratch_pool);
+                  *conflict_report = single_range_conflict_report_create(
+                                       real_source, remaining_range,
+                                       result_pool);
+
                   range.end = end_rev;
                   break;
                 }
@@ -9412,7 +9492,7 @@ do_mergeinfo_aware_dir_merge(svn_mergein
  */
 static svn_error_t *
 do_directory_merge(svn_mergeinfo_catalog_t result_catalog,
-                   svn_merge_range_t **conflicted_range,
+                   single_range_conflict_report_t **conflict_report,
                    const merge_source_t *source,
                    const char *target_abspath,
                    const svn_diff_tree_processor_t *processor,
@@ -9435,14 +9515,14 @@ do_directory_merge(svn_mergeinfo_catalog
   /* If we are not honoring mergeinfo we can skip right to the
      business of merging changes! */
   if (HONOR_MERGEINFO(merge_b))
-    SVN_ERR(do_mergeinfo_aware_dir_merge(result_catalog, conflicted_range,
+    SVN_ERR(do_mergeinfo_aware_dir_merge(result_catalog, conflict_report,
                                          source, target_abspath,
                                          children_with_mergeinfo,
                                          processor, depth,
                                          squelch_mergeinfo_notifications,
                                          merge_b, result_pool, scratch_pool));
   else
-    SVN_ERR(do_mergeinfo_unaware_dir_merge(conflicted_range,
+    SVN_ERR(do_mergeinfo_unaware_dir_merge(conflict_report,
                                            source, target_abspath,
                                            children_with_mergeinfo,
                                            processor, depth,
@@ -9637,8 +9717,9 @@ do_merge(apr_hash_t **modified_subtrees,
     depth = svn_depth_infinity;
 
   /* Set up the diff3 command, so various callers don't have to. */
-  cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
-                                   APR_HASH_KEY_STRING) : NULL;
+  cfg = ctx->config
+        ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
+        : NULL;
   svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
                  SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
 
@@ -9708,7 +9789,7 @@ do_merge(apr_hash_t **modified_subtrees,
       svn_node_kind_t src1_kind;
       merge_source_t *source =
         APR_ARRAY_IDX(merge_sources, i, merge_source_t *);
-      svn_merge_range_t *conflicted_range;
+      single_range_conflict_report_t *conflicted_range_report;
 
       svn_pool_clear(iterpool);
 
@@ -9750,24 +9831,54 @@ do_merge(apr_hash_t **modified_subtrees,
       SVN_ERR(svn_ra_check_path(ra_session1, "", source->loc1->rev,
                                 &src1_kind, iterpool));
 
-      /* Call our merge helpers based on SRC1's kind. */
-      if (src1_kind != svn_node_dir)
-        {
-          SVN_ERR(do_file_merge(result_catalog, &conflicted_range,
-                                source, target->abspath,
-                                processor,
-                                sources_related,
-                                squelch_mergeinfo_notifications,
-                                &merge_cmd_baton, iterpool, iterpool));
-        }
-      else /* Directory */
-        {
-          SVN_ERR(do_directory_merge(result_catalog, &conflicted_range,
-                                     source, target->abspath,
-                                     processor,
-                                     depth, squelch_mergeinfo_notifications,
-                                     &merge_cmd_baton, iterpool, iterpool));
+      /* Run the merge; if there are conflicts, allow the callback to
+       * resolve them, and if it resolves all of them, then run the
+       * merge again with the remaining revision range, until it is all
+       * done. */
+      do
+        {
+          /* Merge as far as possible without resolving any conflicts */
+          if (src1_kind != svn_node_dir)
+            {
+              SVN_ERR(do_file_merge(result_catalog, &conflicted_range_report,
+                                    source, target->abspath,
+                                    processor,
+                                    sources_related,
+                                    squelch_mergeinfo_notifications,
+                                    &merge_cmd_baton, iterpool, iterpool));
+            }
+          else /* Directory */
+            {
+              SVN_ERR(do_directory_merge(result_catalog, &conflicted_range_report,
+                                         source, target->abspath,
+                                         processor,
+                                         depth, squelch_mergeinfo_notifications,
+                                         &merge_cmd_baton, iterpool, iterpool));
+            }
+
+          /* Give the conflict resolver callback the opportunity to
+           * resolve any conflicts that were raised.  If it resolves all
+           * of them, go around again to merge the next sub-range (if any). */
+          if (conflicted_range_report && ctx->conflict_func2 && ! dry_run)
+            {
+              svn_boolean_t conflicts_remain;
+
+              SVN_ERR(svn_client__resolve_conflicts(
+                        &conflicts_remain, merge_cmd_baton.conflicted_paths,
+                        ctx, iterpool));
+              if (conflicts_remain)
+                break;
+
+              merge_cmd_baton.conflicted_paths = NULL;
+              /* Caution: this source is in iterpool */
+              source = conflicted_range_report->remaining_source;
+              conflicted_range_report = NULL;
+            }
+          else
+            break;
         }
+      while (source);
+
       /* The final mergeinfo on TARGET_WCPATH may itself elide. */
       if (! dry_run)
         SVN_ERR(svn_client__elide_mergeinfo(target->abspath, NULL,
@@ -9777,12 +9888,12 @@ do_merge(apr_hash_t **modified_subtrees,
        * range of a multi-pass merge, we raise an error that aborts
        * the merge. The user will be asked to resolve conflicts
        * before merging subsequent revision ranges. */
-      if (conflicted_range)
+      if (conflicted_range_report)
         {
           *conflict_report = conflict_report_create(
-                               target->abspath, conflicted_range,
+                               target->abspath, conflicted_range_report->conflicted_range,
                                (i == merge_sources->nelts - 1
-                                && conflicted_range->end == source->loc2->rev),
+                                && ! conflicted_range_report->remaining_source),
                                result_pool);
           break;
         }
@@ -11474,7 +11585,7 @@ merge_reintegrate_locked(conflict_report
   svn_client__pathrev_t *source_loc;
   merge_source_t *source;
   svn_client__pathrev_t *yc_ancestor;
-  svn_boolean_t use_sleep;
+  svn_boolean_t use_sleep = FALSE;
   svn_error_t *err;
 
   SVN_ERR(open_reintegrate_source_and_target(
@@ -11651,13 +11762,43 @@ svn_client_merge_peg5(const char *source
   conflict_report_t *conflict_report;
 
   /* No ranges to merge?  No problem. */
-  if (ranges_to_merge->nelts == 0)
+  if (ranges_to_merge != NULL && ranges_to_merge->nelts == 0)
     return SVN_NO_ERROR;
 
   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
                                       target_wcpath, ctx, pool));
 
-  if (!dry_run)
+  /* Do an automatic merge if no revision ranges are specified. */
+  if (ranges_to_merge == NULL)
+    {
+      svn_client_automatic_merge_t *merge;
+
+      if (ignore_mergeinfo)
+        return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                _("Cannot merge automatically while "
+                                  "ignoring mergeinfo"));
+
+      /* Find the details of the merge needed. */
+      SVN_ERR(svn_client_find_automatic_merge(&merge,
+                                              source_path_or_url,
+                                              source_peg_revision,
+                                              target_wcpath,
+                                              allow_mixed_rev,
+                                              TRUE /*allow_local_mods*/,
+                                              TRUE /*allow_switched_subtrees*/,
+                                              ctx, pool, pool));
+
+      SVN_ERR(svn_client_do_automatic_merge(merge, target_wcpath, depth,
+                                            diff_ignore_ancestry,
+                                            force_delete, record_only,
+                                            dry_run, merge_options,
+                                            ctx, pool));
+
+      /* We already dealt with returning any conflict error, inside the
+       * above calls. */
+      conflict_report = NULL;
+    }
+  else if (!dry_run)
     SVN_WC__CALL_WITH_WRITE_LOCK(
       merge_peg_locked(&conflict_report,
                        source_path_or_url, source_peg_revision,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/mergeinfo.c Fri Apr  5 05:29:29 2013
@@ -405,9 +405,8 @@ svn_client__get_wc_mergeinfo_catalog(svn
   if (mergeinfo)
     {
       *mergeinfo_cat = apr_hash_make(result_pool);
-      apr_hash_set(*mergeinfo_cat,
-                   apr_pstrdup(result_pool, target_repos_relpath),
-                   APR_HASH_KEY_STRING, mergeinfo);
+      svn_hash_sets(*mergeinfo_cat,
+                    apr_pstrdup(result_pool, target_repos_relpath), mergeinfo);
     }
 
   /* If LOCAL_ABSPATH is a directory and we want the subtree mergeinfo too,
@@ -451,8 +450,7 @@ svn_client__get_wc_mergeinfo_catalog(svn
           if (*mergeinfo_cat == NULL)
             *mergeinfo_cat = apr_hash_make(result_pool);
 
-          apr_hash_set(*mergeinfo_cat, repos_relpath,
-                       APR_HASH_KEY_STRING, subtree_mergeinfo);
+          svn_hash_sets(*mergeinfo_cat, repos_relpath, subtree_mergeinfo);
         }
     }
 
@@ -657,8 +655,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
              || (inherit == svn_mergeinfo_explicit)
              || (repos_relpath
                  && target_mergeinfo_cat_wc
-                 && apr_hash_get(target_mergeinfo_cat_wc, repos_relpath,
-                                 APR_HASH_KEY_STRING))))
+                 && svn_hash_gets(target_mergeinfo_cat_wc, repos_relpath))))
         {
           repos_only = TRUE;
           /* We already have any subtree mergeinfo from the working copy, no
@@ -680,8 +677,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
           SVN_ERR(svn_wc_get_pristine_props(&original_props,
                                             ctx->wc_ctx, local_abspath,
                                             result_pool, scratch_pool));
-          if (!apr_hash_get(original_props, SVN_PROP_MERGEINFO,
-                            APR_HASH_KEY_STRING))
+          if (!svn_hash_gets(original_props, SVN_PROP_MERGEINFO))
             {
               apr_pool_t *sesspool = NULL;
 
@@ -700,9 +696,7 @@ svn_client__get_wc_or_repos_mergeinfo_ca
                         result_pool, scratch_pool));
 
               if (target_mergeinfo_cat_repos
-                  && apr_hash_get(target_mergeinfo_cat_repos,
-                                  repos_relpath,
-                                  APR_HASH_KEY_STRING))
+                  && svn_hash_gets(target_mergeinfo_cat_repos, repos_relpath))
                 {
                   if (inherited_p)
                     *inherited_p = TRUE;
@@ -1149,10 +1143,8 @@ svn_client__elide_mergeinfo_catalog(svn_
           if (path_suffix)
             {
               SVN_ERR(should_elide_mergeinfo(&elides,
-                                         apr_hash_get(mergeinfo_catalog, top,
-                                                      APR_HASH_KEY_STRING),
-                                         apr_hash_get(mergeinfo_catalog, path,
-                                                      APR_HASH_KEY_STRING),
+                                         svn_hash_gets(mergeinfo_catalog, top),
+                                         svn_hash_gets(mergeinfo_catalog, path),
                                          path_suffix,
                                          iterpool));
 
@@ -1169,7 +1161,7 @@ svn_client__elide_mergeinfo_catalog(svn_
   for (i = 0; i < elidable_paths->nelts; i++)
     {
       const char *path = APR_ARRAY_IDX(elidable_paths, i, const char *);
-      apr_hash_set(mergeinfo_catalog, path, APR_HASH_KEY_STRING, NULL);
+      svn_hash_sets(mergeinfo_catalog, path, NULL);
     }
 
   return SVN_NO_ERROR;
@@ -1402,8 +1394,8 @@ filter_log_entry_with_rangelist(void *ba
           if (ancestor_is_self /* Explicit mergeinfo on TARGET_PATH_AFFECTED */
               && (change->action != 'M'))
             {
-              svn_rangelist_t *rangelist = apr_hash_get(
-                nearest_ancestor_mergeinfo, path, APR_HASH_KEY_STRING);
+              svn_rangelist_t *rangelist =
+                  svn_hash_gets(nearest_ancestor_mergeinfo, path);
               svn_merge_range_t *youngest_range = APR_ARRAY_IDX(
                 rangelist, rangelist->nelts - 1, svn_merge_range_t *);
 
@@ -1496,6 +1488,7 @@ logs_for_mergeinfo_rangelist(const char 
                              const apr_array_header_t *merge_source_fspaths,
                              svn_boolean_t filtering_merged,
                              const svn_rangelist_t *rangelist,
+                             svn_boolean_t oldest_revs_first,
                              svn_mergeinfo_catalog_t target_mergeinfo_catalog,
                              const char *target_fspath,
                              svn_boolean_t discover_changed_paths,
@@ -1557,8 +1550,12 @@ logs_for_mergeinfo_rangelist(const char 
   /* Drive the log. */
   revision_ranges = apr_array_make(scratch_pool, 1,
                                    sizeof(svn_opt_revision_range_t *));
-  APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
-    = svn_opt__revision_range_create(&oldest_rev, &youngest_rev, scratch_pool);
+  if (oldest_revs_first)
+    APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
+      = svn_opt__revision_range_create(&oldest_rev, &youngest_rev, scratch_pool);
+  else
+    APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
+      = svn_opt__revision_range_create(&youngest_rev, &oldest_rev, scratch_pool);
   SVN_ERR(svn_client_log5(target, &youngest_rev, revision_ranges,
                           0, discover_changed_paths, FALSE, FALSE, revprops,
                           filter_log_entry_with_rangelist, &fleb, ctx,
@@ -1597,10 +1594,10 @@ mergeinfo_relpaths_to_urls(apr_hash_t **
           const char *key = svn__apr_hash_index_key(hi);
           void *val = svn__apr_hash_index_val(hi);
 
-          apr_hash_set(full_path_mergeinfo,
-                       svn_path_url_add_component2(repos_root_url, key + 1,
-                                                   result_pool),
-                       APR_HASH_KEY_STRING, val);
+          svn_hash_sets(full_path_mergeinfo,
+                        svn_path_url_add_component2(repos_root_url, key + 1,
+                                                    result_pool),
+                        val);
         }
       *out_mergeinfo = full_path_mergeinfo;
     }
@@ -1642,8 +1639,7 @@ svn_client_mergeinfo_get_merged(apr_hash
           SVN_ERR_ASSERT(repos_relpath != NULL); /* Or get_mergeinfo failed */
         }
 
-      mergeinfo = apr_hash_get(mergeinfo_cat, repos_relpath,
-                               APR_HASH_KEY_STRING);
+      mergeinfo = svn_hash_gets(mergeinfo_cat, repos_relpath);
     }
   else
     {
@@ -1691,6 +1687,7 @@ svn_client_mergeinfo_log2(svn_boolean_t 
   apr_hash_index_t *hi_catalog;
   apr_hash_index_t *hi;
   apr_pool_t *iterpool;
+  svn_boolean_t oldest_revs_first = TRUE;
 
   /* We currently only support depth = empty | infinity. */
   if (depth != svn_depth_infinity && depth != svn_depth_empty)
@@ -1760,10 +1757,8 @@ svn_client_mergeinfo_log2(svn_boolean_t 
       else
         {
           target_mergeinfo_cat = apr_hash_make(scratch_pool);
-          apr_hash_set(target_mergeinfo_cat,
-                       target_repos_relpath,
-                       APR_HASH_KEY_STRING,
-                       apr_hash_make(scratch_pool));
+          svn_hash_sets(target_mergeinfo_cat, target_repos_relpath,
+                        apr_hash_make(scratch_pool));
         }
     }
 
@@ -1810,9 +1805,13 @@ svn_client_mergeinfo_log2(svn_boolean_t 
                                             source_end_revision,
                                             sesspool));
     SVN_ERR(svn_client__get_history_as_mergeinfo(&source_history, NULL,
-                                                 pathrev, end_rev, start_rev,
+                                                 pathrev,
+                                                 MAX(end_rev, start_rev),
+                                                 MIN(end_rev, start_rev),
                                                  source_session, ctx,
                                                  scratch_pool));
+    if (start_rev > end_rev)
+      oldest_revs_first = FALSE;
 
     /* Close the source and target sessions. */
     svn_pool_destroy(sesspool);
@@ -1933,18 +1932,17 @@ svn_client_mergeinfo_log2(svn_boolean_t 
           SVN_ERR(svn_rangelist__merge_many(subtree_merged_rangelist,
                                             merged, scratch_pool, iterpool));
 
-          apr_hash_set(inheritable_subtree_merges, subtree_path,
-                       APR_HASH_KEY_STRING, subtree_merged_rangelist);
+          svn_hash_sets(inheritable_subtree_merges, subtree_path,
+                        subtree_merged_rangelist);
         }
       else
         {
           /* Map SUBTREE_PATH to an empty rangelist if there was nothing
              fully merged. e.g. Only empty or non-inheritable mergeinfo
              on the subtree or mergeinfo unrelated to the source. */
-          apr_hash_set(inheritable_subtree_merges, subtree_path,
-                       APR_HASH_KEY_STRING,
-                       apr_array_make(scratch_pool, 0,
-                       sizeof(svn_merge_range_t *)));
+          svn_hash_sets(inheritable_subtree_merges, subtree_path,
+                        apr_array_make(scratch_pool, 0,
+                                       sizeof(svn_merge_range_t *)));
         }
     }
 
@@ -2076,6 +2074,7 @@ svn_client_mergeinfo_log2(svn_boolean_t 
   SVN_ERR(logs_for_mergeinfo_rangelist(log_target, merge_source_fspaths,
                                        finding_merged,
                                        master_inheritable_rangelist,
+                                       oldest_revs_first,
                                        target_mergeinfo_cat,
                                        svn_fspath__join("/",
                                                         target_repos_relpath,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/patch.c Fri Apr  5 05:29:29 2013
@@ -313,8 +313,7 @@ obtain_eol_and_keywords_for_file(apr_has
 
   SVN_ERR(svn_wc_prop_list2(&props, wc_ctx, local_abspath,
                             scratch_pool, scratch_pool));
-  keywords_val = apr_hash_get(props, SVN_PROP_KEYWORDS,
-                              APR_HASH_KEY_STRING);
+  keywords_val = svn_hash_gets(props, SVN_PROP_KEYWORDS);
   if (keywords_val)
     {
       svn_revnum_t changed_rev;
@@ -339,8 +338,7 @@ obtain_eol_and_keywords_for_file(apr_has
                                         author, result_pool));
     }
 
-  eol_style_val = apr_hash_get(props, SVN_PROP_EOL_STYLE,
-                               APR_HASH_KEY_STRING);
+  eol_style_val = svn_hash_gets(props, SVN_PROP_EOL_STYLE);
   if (eol_style_val)
     {
       svn_subst_eol_style_from_value(eol_style,
@@ -1143,8 +1141,7 @@ init_patch_target(patch_target_t **patch
                                        prop_patch->operation,
                                        wc_ctx, target->local_abspath,
                                        result_pool, scratch_pool));
-              apr_hash_set(target->prop_targets, prop_name,
-                           APR_HASH_KEY_STRING, prop_target);
+              svn_hash_sets(target->prop_targets, prop_name, prop_target);
             }
         }
     }
@@ -2188,8 +2185,7 @@ apply_one_patch(patch_target_t **patch_t
         target->is_special = TRUE;
 
       /* We'll store matched hunks in prop_content. */
-      prop_target = apr_hash_get(target->prop_targets, prop_name,
-                                 APR_HASH_KEY_STRING);
+      prop_target = svn_hash_gets(target->prop_targets, prop_name);
 
       for (i = 0; i < prop_patch->hunks->nelts; i++)
         {

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/prop_commands.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/prop_commands.c Fri Apr  5 05:29:29 2013
@@ -88,7 +88,7 @@ get_file_for_validation(const svn_string
                           pool));
 
   if (mime_type)
-    *mime_type = apr_hash_get(props, SVN_PROP_MIME_TYPE, APR_HASH_KEY_STRING);
+    *mime_type = svn_hash_gets(props, SVN_PROP_MIME_TYPE);
 
   return SVN_NO_ERROR;
 }
@@ -612,8 +612,7 @@ remote_propget(apr_hash_t *props,
         {
           svn_prop_inherited_item_t *iprop =
             APR_ARRAY_IDX((*inherited_props), i, svn_prop_inherited_item_t *);
-          svn_string_t *iprop_val = apr_hash_get(iprop->prop_hash, propname,
-                                                 APR_HASH_KEY_STRING);
+          svn_string_t *iprop_val = svn_hash_gets(iprop->prop_hash, propname);
 
           if (iprop_val)
             {
@@ -622,10 +621,9 @@ remote_propget(apr_hash_t *props,
               new_iprop->path_or_url =
                 apr_pstrdup(result_pool, iprop->path_or_url);
               new_iprop->prop_hash = apr_hash_make(result_pool);
-              apr_hash_set(new_iprop->prop_hash,
-                           apr_pstrdup(result_pool, propname),
-                           APR_HASH_KEY_STRING,
-                           svn_string_dup(iprop_val, result_pool));
+              svn_hash_sets(new_iprop->prop_hash,
+                            apr_pstrdup(result_pool, propname),
+                            svn_string_dup(iprop_val, result_pool));
               APR_ARRAY_PUSH(final_iprops, svn_prop_inherited_item_t *) =
                 new_iprop;
             }
@@ -634,10 +632,11 @@ remote_propget(apr_hash_t *props,
     }
 
   if (prop_hash
-      && (val = apr_hash_get(prop_hash, propname, APR_HASH_KEY_STRING)))
+      && (val = svn_hash_gets(prop_hash, propname)))
     {
-      apr_hash_set(props, apr_pstrdup(result_pool, target_full_url),
-                   APR_HASH_KEY_STRING, svn_string_dup(val, result_pool));
+      svn_hash_sets(props,
+                    apr_pstrdup(result_pool, target_full_url),
+                    svn_string_dup(val, result_pool));
     }
 
   if (depth >= svn_depth_files
@@ -704,9 +703,8 @@ recursive_propget_receiver(void *baton,
   if (apr_hash_count(props))
     {
       apr_hash_index_t *hi = apr_hash_first(scratch_pool, props);
-      apr_hash_set(b->props, apr_pstrdup(b->pool, local_abspath),
-                   APR_HASH_KEY_STRING,
-                   svn_string_dup(svn__apr_hash_index_val(hi), b->pool));
+      svn_hash_sets(b->props, apr_pstrdup(b->pool, local_abspath),
+                    svn_string_dup(svn__apr_hash_index_val(hi), b->pool));
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/ra.c Fri Apr  5 05:29:29 2013
@@ -26,6 +26,7 @@
 #include <apr_pools.h>
 
 #include "svn_error.h"
+#include "svn_hash.h"
 #include "svn_pools.h"
 #include "svn_string.h"
 #include "svn_sorts.h"
@@ -409,13 +410,13 @@ svn_client__open_ra_session_internal(svn
           *corrected_url = corrected;
 
           /* Make sure we've not attempted this URL before. */
-          if (apr_hash_get(attempted, corrected, APR_HASH_KEY_STRING))
+          if (svn_hash_gets(attempted, corrected))
             return svn_error_createf(SVN_ERR_CLIENT_CYCLE_DETECTED, NULL,
                                      _("Redirect cycle detected for URL '%s'"),
                                      corrected);
 
           /* Remember this CORRECTED_URL so we don't wind up in a loop. */
-          apr_hash_set(attempted, corrected, APR_HASH_KEY_STRING, (void *)1);
+          svn_hash_sets(attempted, corrected, (void *)1);
           base_url = corrected;
         }
     }
@@ -1052,8 +1053,7 @@ svn_client__ra_provide_base(svn_stream_t
   const char *local_abspath;
   svn_error_t *err;
 
-  local_abspath = apr_hash_get(reb->relpath_map, repos_relpath,
-                               APR_HASH_KEY_STRING);
+  local_abspath = svn_hash_gets(reb->relpath_map, repos_relpath);
   if (!local_abspath)
     {
       *contents = NULL;
@@ -1097,8 +1097,7 @@ svn_client__ra_provide_props(apr_hash_t 
   const char *local_abspath;
   svn_error_t *err;
 
-  local_abspath = apr_hash_get(reb->relpath_map, repos_relpath,
-                               APR_HASH_KEY_STRING);
+  local_abspath = svn_hash_gets(reb->relpath_map, repos_relpath);
   if (!local_abspath)
     {
       *props = NULL;
@@ -1140,8 +1139,7 @@ svn_client__ra_get_copysrc_kind(svn_node
   struct ra_ev2_baton *reb = baton;
   const char *local_abspath;
 
-  local_abspath = apr_hash_get(reb->relpath_map, repos_relpath,
-                               APR_HASH_KEY_STRING);
+  local_abspath = svn_hash_gets(reb->relpath_map, repos_relpath);
   if (!local_abspath)
     {
       *kind = svn_node_unknown;

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/repos_diff.c Fri Apr  5 05:29:29 2013
@@ -395,9 +395,8 @@ remove_non_prop_changes(apr_hash_t *pris
 
       if (change->value)
         {
-          const svn_string_t *old_val = apr_hash_get(pristine_props,
-                                                     change->name,
-                                                     APR_HASH_KEY_STRING);
+          const svn_string_t *old_val = svn_hash_gets(pristine_props,
+                                                      change->name);
 
           if (old_val && svn_string_compare(old_val, change->value))
             {

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/resolved.c Fri Apr  5 05:29:29 2013
@@ -27,12 +27,17 @@
 
 /*** Includes. ***/
 
+#include <stdlib.h>
+
 #include "svn_types.h"
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_error.h"
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
+#include "svn_pools.h"
+#include "svn_hash.h"
+#include "svn_sorts.h"
 #include "client.h"
 #include "private/svn_wc_private.h"
 
@@ -41,6 +46,66 @@
 /*** Code. ***/
 
 svn_error_t *
+svn_client__resolve_conflicts(svn_boolean_t *conflicts_remain,
+                              apr_hash_t *conflicted_paths,
+                              svn_client_ctx_t *ctx,
+                              apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_array_header_t *array;
+  int i;
+
+  if (conflicts_remain)
+    *conflicts_remain = FALSE;
+
+  SVN_ERR(svn_hash_keys(&array, conflicted_paths, scratch_pool));
+  qsort(array->elts, array->nelts, array->elt_size,
+        svn_sort_compare_paths);
+
+  for (i = 0; i < array->nelts; i++)
+    {
+      const char *local_abspath = APR_ARRAY_IDX(array, i, const char *);
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_wc__resolve_conflicts(ctx->wc_ctx, local_abspath,
+                                        svn_depth_empty,
+                                        TRUE /* resolve_text */,
+                                        "" /* resolve_prop (ALL props) */,
+                                        TRUE /* resolve_tree */,
+                                        svn_wc_conflict_choose_unspecified,
+                                        ctx->conflict_func2,
+                                        ctx->conflict_baton2,
+                                        ctx->cancel_func, ctx->cancel_baton,
+                                        ctx->notify_func2, ctx->notify_baton2,
+                                        iterpool));
+
+      if (conflicts_remain)
+        {
+          svn_error_t *err;
+          svn_boolean_t text_c, prop_c, tree_c;
+
+          err = svn_wc_conflicted_p3(&text_c, &prop_c, &tree_c,
+                                     ctx->wc_ctx, local_abspath,
+                                     iterpool);
+          if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+            {
+              svn_error_clear(err);
+              text_c = prop_c = tree_c = FALSE;
+            }
+          else
+            {
+              SVN_ERR(err);
+            }
+          if (text_c || prop_c || tree_c)
+            *conflicts_remain = TRUE;
+        }
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_client_resolve(const char *path,
                    svn_depth_t depth,
                    svn_wc_conflict_choice_t conflict_choice,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/revert.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/revert.c Fri Apr  5 05:29:29 2013
@@ -31,6 +31,7 @@
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_dirent_uri.h"
+#include "svn_hash.h"
 #include "svn_pools.h"
 #include "svn_error.h"
 #include "svn_time.h"
@@ -135,8 +136,9 @@ svn_client_revert2(const apr_array_heade
                                  _("'%s' is not a local path"), path);
     }
 
-  cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
-                                   APR_HASH_KEY_STRING) : NULL;
+  cfg = ctx->config
+        ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
+        : NULL;
 
   SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
                               SVN_CONFIG_SECTION_MISCELLANY,
@@ -158,7 +160,9 @@ svn_client_revert2(const apr_array_heade
           && ((err = ctx->cancel_func(ctx->cancel_baton))))
         goto errorful;
 
-      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+      err = svn_dirent_get_absolute(&local_abspath, path, pool);
+      if (err)
+        goto errorful;
 
       baton.local_abspath = local_abspath;
       baton.depth = depth;
@@ -166,8 +170,9 @@ svn_client_revert2(const apr_array_heade
       baton.changelists = changelists;
       baton.ctx = ctx;
 
-      SVN_ERR(svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath,
-                                pool));
+      err = svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath, pool);
+      if (err)
+        goto errorful;
       lock_target = wc_root ? local_abspath
                             : svn_dirent_dirname(local_abspath, pool);
       err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx,

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/status.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/status.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/status.c Fri Apr  5 05:29:29 2013
@@ -87,8 +87,7 @@ tweak_status(void *baton,
      transmission.  */
   if (sb->changelist_hash
       && (! status->changelist
-          || ! apr_hash_get(sb->changelist_hash, status->changelist,
-                            APR_HASH_KEY_STRING)))
+          || ! svn_hash_gets(sb->changelist_hash, status->changelist)))
     {
       return SVN_NO_ERROR;
     }

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/switch.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/switch.c Fri Apr  5 05:29:29 2013
@@ -29,6 +29,7 @@
 
 #include "svn_client.h"
 #include "svn_error.h"
+#include "svn_hash.h"
 #include "svn_time.h"
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
@@ -55,8 +56,35 @@
 */
 
 
+/* A conflict callback that simply records the conflicted path in BATON.
+
+   Implements svn_wc_conflict_resolver_func2_t.
+*/
+static svn_error_t *
+record_conflict(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)
+{
+  apr_hash_t *conflicted_paths = baton;
+
+  svn_hash_sets(conflicted_paths,
+                apr_pstrdup(apr_hash_pool_get(conflicted_paths),
+                            description->local_abspath), "");
+  *result = svn_wc_create_conflict_result(svn_wc_conflict_choose_postpone,
+                                          NULL, result_pool);
+  return SVN_NO_ERROR;
+}
+
+/* ...
+
+   Add the paths of any conflict victims to CONFLICTED_PATHS, if that
+   is not null.
+*/
 static svn_error_t *
 switch_internal(svn_revnum_t *result_rev,
+                apr_hash_t *conflicted_paths,
                 const char *local_abspath,
                 const char *anchor_abspath,
                 const char *switch_url,
@@ -77,23 +105,19 @@ switch_internal(svn_revnum_t *result_rev
   svn_client__pathrev_t *switch_loc;
   svn_ra_session_t *ra_session;
   svn_revnum_t revnum;
-  svn_error_t *err = SVN_NO_ERROR;
   const char *diff3_cmd;
   apr_hash_t *wcroot_iprops;
   apr_array_header_t *inherited_props;
   svn_boolean_t use_commit_times;
-  svn_boolean_t sleep_here = FALSE;
-  svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
   const svn_delta_editor_t *switch_editor;
   void *switch_edit_baton;
   const char *preserved_exts_str;
   apr_array_header_t *preserved_exts;
   svn_boolean_t server_supports_depth;
   struct svn_client__dirent_fetcher_baton_t dfb;
-  svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
-                                                 SVN_CONFIG_CATEGORY_CONFIG,
-                                                 APR_HASH_KEY_STRING)
-                                  : NULL;
+  svn_config_t *cfg = ctx->config
+                      ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
+                      : NULL;
 
   /* An unknown depth can't be sticky. */
   if (depth == svn_depth_unknown)
@@ -269,8 +293,7 @@ switch_internal(svn_revnum_t *result_rev
           SVN_ERR(svn_ra_get_inherited_props(ra_session, &inherited_props,
                                              "", switch_loc->rev, pool,
                                              pool));
-          apr_hash_set(wcroot_iprops, local_abspath, APR_HASH_KEY_STRING,
-                       inherited_props);
+          svn_hash_sets(wcroot_iprops, local_abspath, inherited_props);
         }
     }
 
@@ -293,7 +316,8 @@ switch_internal(svn_revnum_t *result_rev
                                     server_supports_depth,
                                     diff3_cmd, preserved_exts,
                                     svn_client__dirent_fetcher, &dfb,
-                                    ctx->conflict_func2, ctx->conflict_baton2,
+                                    conflicted_paths ? record_conflict : NULL,
+                                    conflicted_paths,
                                     NULL, NULL,
                                     ctx->cancel_func, ctx->cancel_baton,
                                     ctx->notify_func2, ctx->notify_baton2,
@@ -311,24 +335,22 @@ switch_internal(svn_revnum_t *result_rev
                             switch_editor, switch_edit_baton,
                             pool, pool));
 
+  /* Past this point, we assume the WC is going to be modified so we will
+   * need to sleep for timestamps. */
+  if (! use_commit_times)
+    *timestamp_sleep = TRUE;
+
   /* Drive the reporter structure, describing the revisions within
      PATH.  When we call reporter->finish_report, the update_editor
      will be driven by svn_repos_dir_delta2. */
-  err = svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
-                                report_baton, TRUE, depth, (! depth_is_sticky),
-                                (! server_supports_depth),
-                                use_commit_times,
-                                ctx->cancel_func, ctx->cancel_baton,
-                                ctx->notify_func2, ctx->notify_baton2, pool);
-
-  if (err)
-    {
-      /* Don't rely on the error handling to handle the sleep later, do
-         it now */
-      svn_io_sleep_for_timestamps(local_abspath, pool);
-      return svn_error_trace(err);
-    }
-  *use_sleep = TRUE;
+  SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
+                                  report_baton, TRUE,
+                                  depth, (! depth_is_sticky),
+                                  (! server_supports_depth),
+                                  use_commit_times,
+                                  ctx->cancel_func, ctx->cancel_baton,
+                                  ctx->notify_func2, ctx->notify_baton2,
+                                  pool));
 
   /* We handle externals after the switch is complete, so that
      handling external items (and any errors therefrom) doesn't delay
@@ -346,19 +368,10 @@ switch_internal(svn_revnum_t *result_rev
                                            new_depths,
                                            switch_loc->repos_root_url,
                                            local_abspath,
-                                           depth, use_sleep,
+                                           depth, timestamp_sleep,
                                            ctx, pool));
     }
 
-  /* Sleep to ensure timestamp integrity (we do this regardless of
-     errors in the actual switch operation(s)). */
-  if (sleep_here)
-    svn_io_sleep_for_timestamps(local_abspath, pool);
-
-  /* Return errors we might have sustained. */
-  if (err)
-    return svn_error_trace(err);
-
   /* Let everyone know we're finished here. */
   if (ctx->notify_func2)
     {
@@ -398,6 +411,8 @@ svn_client__switch_internal(svn_revnum_t
   const char *local_abspath, *anchor_abspath;
   svn_boolean_t acquired_lock;
   svn_error_t *err, *err1, *err2;
+  apr_hash_t *conflicted_paths
+    = ctx->conflict_func2 ? apr_hash_make(pool) : NULL;
 
   SVN_ERR_ASSERT(path);
 
@@ -414,13 +429,21 @@ svn_client__switch_internal(svn_revnum_t
   acquired_lock = (err == SVN_NO_ERROR);
   svn_error_clear(err);
 
-  err1 = switch_internal(result_rev, local_abspath, anchor_abspath,
+  err1 = switch_internal(result_rev, conflicted_paths,
+                         local_abspath, anchor_abspath,
                          switch_url, peg_revision, revision,
                          depth, depth_is_sticky,
                          ignore_externals,
                          allow_unver_obstructions, ignore_ancestry,
                          timestamp_sleep, ctx, pool);
 
+  /* Give the conflict resolver callback the opportunity to
+   * resolve any conflicts that were raised. */
+  if (! err1 && ctx->conflict_func2)
+    {
+      err1 = svn_client__resolve_conflicts(NULL, conflicted_paths, ctx, pool);
+    }
+
   if (acquired_lock)
     err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
   else
@@ -443,13 +466,23 @@ svn_client_switch3(svn_revnum_t *result_
                    svn_client_ctx_t *ctx,
                    apr_pool_t *pool)
 {
+  svn_error_t *err;
+  svn_boolean_t sleep_here = FALSE;
+
   if (svn_path_is_url(path))
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                              _("'%s' is not a local path"), path);
 
-  return svn_client__switch_internal(result_rev, path, switch_url,
-                                     peg_revision, revision, depth,
-                                     depth_is_sticky, ignore_externals,
-                                     allow_unver_obstructions,
-                                     ignore_ancestry, NULL, ctx, pool);
+  err = svn_client__switch_internal(result_rev, path, switch_url,
+                                    peg_revision, revision, depth,
+                                    depth_is_sticky, ignore_externals,
+                                    allow_unver_obstructions,
+                                    ignore_ancestry, &sleep_here, ctx, pool);
+
+  /* Sleep to ensure timestamp integrity (we do this regardless of
+     errors in the actual switch operation(s)). */
+  if (sleep_here)
+    svn_io_sleep_for_timestamps(path, pool);
+
+  return svn_error_trace(err);
 }

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/update.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/update.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/update.c Fri Apr  5 05:29:29 2013
@@ -27,6 +27,7 @@
 
 /*** Includes. ***/
 
+#include "svn_hash.h"
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_error.h"
@@ -160,6 +161,27 @@ is_empty_wc(svn_boolean_t *clean_checkou
   return svn_io_dir_close(dir);
 }
 
+/* A conflict callback that simply records the conflicted path in BATON.
+
+   Implements svn_wc_conflict_resolver_func2_t.
+*/
+static svn_error_t *
+record_conflict(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)
+{
+  apr_hash_t *conflicted_paths = baton;
+
+  svn_hash_sets(conflicted_paths,
+                apr_pstrdup(apr_hash_pool_get(conflicted_paths),
+                            description->local_abspath), "");
+  *result = svn_wc_create_conflict_result(svn_wc_conflict_choose_postpone,
+                                          NULL, result_pool);
+  return SVN_NO_ERROR;
+}
+
 /* This is a helper for svn_client__update_internal(), which see for
    an explanation of most of these parameters.  Some stuff that's
    unique is as follows:
@@ -171,9 +193,13 @@ is_empty_wc(svn_boolean_t *clean_checkou
    If NOTIFY_SUMMARY is set (and there's a notification handler in
    CTX), transmit the final update summary upon successful
    completion of the update.
+
+   Add the paths of any conflict victims to CONFLICTED_PATHS, if that
+   is not null.
 */
 static svn_error_t *
 update_internal(svn_revnum_t *result_rev,
+                apr_hash_t *conflicted_paths,
                 const char *local_abspath,
                 const char *anchor_abspath,
                 const svn_opt_revision_t *revision,
@@ -197,11 +223,8 @@ update_internal(svn_revnum_t *result_rev
   const char *repos_relpath;
   const char *repos_uuid;
   const char *anchor_url;
-  svn_error_t *err;
   svn_revnum_t revnum;
   svn_boolean_t use_commit_times;
-  svn_boolean_t sleep_here = FALSE;
-  svn_boolean_t *use_sleep = timestamp_sleep ? timestamp_sleep : &sleep_here;
   svn_boolean_t clean_checkout = FALSE;
   const char *diff3_cmd;
   apr_hash_t *wcroot_iprops;
@@ -213,9 +236,9 @@ update_internal(svn_revnum_t *result_rev
   svn_boolean_t server_supports_depth;
   svn_boolean_t cropping_target;
   svn_boolean_t target_conflicted = FALSE;
-  svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
-                                                 SVN_CONFIG_CATEGORY_CONFIG,
-                                                 APR_HASH_KEY_STRING) : NULL;
+  svn_config_t *cfg = ctx->config
+                      ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
+                      : NULL;
 
   if (result_rev)
     *result_rev = SVN_INVALID_REVNUM;
@@ -239,6 +262,7 @@ update_internal(svn_revnum_t *result_rev
   /* It does not make sense to update conflict victims. */
   if (repos_relpath)
     {
+      svn_error_t *err;
       svn_boolean_t text_conflicted, prop_conflicted;
 
       anchor_url = svn_path_url_add_component2(repos_root_url, repos_relpath,
@@ -407,7 +431,8 @@ update_internal(svn_revnum_t *result_rev
                                     clean_checkout,
                                     diff3_cmd, preserved_exts,
                                     svn_client__dirent_fetcher, &dfb,
-                                    ctx->conflict_func2, ctx->conflict_baton2,
+                                    conflicted_paths ? record_conflict : NULL,
+                                    conflicted_paths,
                                     NULL, NULL,
                                     ctx->cancel_func, ctx->cancel_baton,
                                     ctx->notify_func2, ctx->notify_baton2,
@@ -422,25 +447,22 @@ update_internal(svn_revnum_t *result_rev
                              : svn_depth_unknown),
                             FALSE, update_editor, update_edit_baton, pool));
 
+  /* Past this point, we assume the WC is going to be modified so we will
+   * need to sleep for timestamps. */
+  if (! use_commit_times)
+    *timestamp_sleep = TRUE;
+
   /* Drive the reporter structure, describing the revisions within
      PATH.  When we call reporter->finish_report, the
      update_editor will be driven by svn_repos_dir_delta2. */
-  err = svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
-                                report_baton, TRUE, depth, (! depth_is_sticky),
-                                (! server_supports_depth),
-                                use_commit_times,
-                                ctx->cancel_func, ctx->cancel_baton,
-                                ctx->notify_func2, ctx->notify_baton2,
-                                pool);
-
-  if (err)
-    {
-      /* Don't rely on the error handling to handle the sleep later, do
-         it now */
-      svn_io_sleep_for_timestamps(local_abspath, pool);
-      return svn_error_trace(err);
-    }
-  *use_sleep = TRUE;
+  SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
+                                  report_baton, TRUE,
+                                  depth, (! depth_is_sticky),
+                                  (! server_supports_depth),
+                                  use_commit_times,
+                                  ctx->cancel_func, ctx->cancel_baton,
+                                  ctx->notify_func2, ctx->notify_baton2,
+                                  pool));
 
   /* We handle externals after the update is complete, so that
      handling external items (and any errors therefrom) doesn't delay
@@ -458,13 +480,10 @@ update_internal(svn_revnum_t *result_rev
       SVN_ERR(svn_client__handle_externals(new_externals,
                                            new_depths,
                                            repos_root_url, local_abspath,
-                                           depth, use_sleep,
+                                           depth, timestamp_sleep,
                                            ctx, pool));
     }
 
-  if (sleep_here)
-    svn_io_sleep_for_timestamps(local_abspath, pool);
-
   /* Let everyone know we're finished here (unless we're asked not to). */
   if (ctx->notify_func2 && notify_summary)
     {
@@ -504,6 +523,8 @@ svn_client__update_internal(svn_revnum_t
   const char *anchor_abspath, *lockroot_abspath;
   svn_error_t *err;
   svn_opt_revision_t peg_revision = *revision;
+  apr_hash_t *conflicted_paths
+    = ctx->conflict_func2 ? apr_hash_make(pool) : NULL;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(! (innerupdate && make_parents));
@@ -544,7 +565,9 @@ svn_client__update_internal(svn_revnum_t
         {
           const char *missing_parent =
             APR_ARRAY_IDX(missing_parents, i, const char *);
-          err = update_internal(result_rev, missing_parent, anchor_abspath,
+
+          err = update_internal(result_rev, conflicted_paths,
+                                missing_parent, anchor_abspath,
                                 &peg_revision, svn_depth_empty, FALSE,
                                 ignore_externals, allow_unver_obstructions,
                                 adds_as_modification, timestamp_sleep,
@@ -568,11 +591,20 @@ svn_client__update_internal(svn_revnum_t
       anchor_abspath = lockroot_abspath;
     }
 
-  err = update_internal(result_rev, local_abspath, anchor_abspath,
+  err = update_internal(result_rev, conflicted_paths,
+                        local_abspath, anchor_abspath,
                         &peg_revision, depth, depth_is_sticky,
                         ignore_externals, allow_unver_obstructions,
                         adds_as_modification, timestamp_sleep,
                         TRUE, ctx, pool);
+
+  /* Give the conflict resolver callback the opportunity to
+   * resolve any conflicts that were raised. */
+  if (! err && ctx->conflict_func2)
+    {
+      err = svn_client__resolve_conflicts(NULL, conflicted_paths, ctx, pool);
+    }
+
  cleanup:
   err = svn_error_compose_create(
             err,
@@ -599,6 +631,7 @@ svn_client_update4(apr_array_header_t **
   apr_pool_t *iterpool = svn_pool_create(pool);
   const char *path = NULL;
   svn_boolean_t sleep = FALSE;
+  svn_error_t *err = SVN_NO_ERROR;
 
   if (result_revs)
     *result_revs = apr_array_make(pool, paths->nelts, sizeof(svn_revnum_t));
@@ -614,7 +647,6 @@ svn_client_update4(apr_array_header_t **
 
   for (i = 0; i < paths->nelts; ++i)
     {
-      svn_error_t *err = SVN_NO_ERROR;
       svn_revnum_t result_rev;
       const char *local_abspath;
       path = APR_ARRAY_IDX(paths, i, const char *);
@@ -622,9 +654,15 @@ svn_client_update4(apr_array_header_t **
       svn_pool_clear(iterpool);
 
       if (ctx->cancel_func)
-        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+        {
+          err = ctx->cancel_func(ctx->cancel_baton);
+          if (err)
+            goto cleanup;
+        }
 
-      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, iterpool));
+      err = svn_dirent_get_absolute(&local_abspath, path, iterpool);
+      if (err)
+        goto cleanup;
       err = svn_client__update_internal(&result_rev, local_abspath,
                                         revision, depth, depth_is_sticky,
                                         ignore_externals,
@@ -637,10 +675,11 @@ svn_client_update4(apr_array_header_t **
 
       if (err)
         {
-          if(err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
-            return svn_error_trace(err);
+          if (err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+            goto cleanup;
 
           svn_error_clear(err);
+          err = SVN_NO_ERROR;
 
           /* SVN_ERR_WC_NOT_WORKING_COPY: it's not versioned */
 
@@ -659,8 +698,9 @@ svn_client_update4(apr_array_header_t **
     }
   svn_pool_destroy(iterpool);
 
+ cleanup:
   if (sleep)
     svn_io_sleep_for_timestamps((paths->nelts == 1) ? path : NULL, pool);
 
-  return SVN_NO_ERROR;
+  return svn_error_trace(err);
 }

Modified: subversion/branches/verify-keep-going/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_client/util.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_client/util.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_client/util.c Fri Apr  5 05:29:29 2013
@@ -24,6 +24,7 @@
 #include <apr_pools.h>
 #include <apr_strings.h>
 
+#include "svn_hash.h"
 #include "svn_pools.h"
 #include "svn_error.h"
 #include "svn_types.h"
@@ -349,7 +350,7 @@ fetch_props_func(apr_hash_t **props,
   struct shim_callbacks_baton *scb = baton;
   const char *local_abspath;
 
-  local_abspath = apr_hash_get(scb->relpath_map, path, APR_HASH_KEY_STRING);
+  local_abspath = svn_hash_gets(scb->relpath_map, path);
   if (!local_abspath)
     {
       *props = apr_hash_make(result_pool);
@@ -376,7 +377,7 @@ fetch_kind_func(svn_node_kind_t *kind,
   struct shim_callbacks_baton *scb = baton;
   const char *local_abspath;
 
-  local_abspath = apr_hash_get(scb->relpath_map, path, APR_HASH_KEY_STRING);
+  local_abspath = svn_hash_gets(scb->relpath_map, path);
   if (!local_abspath)
     {
       *kind = svn_node_unknown;
@@ -403,7 +404,7 @@ fetch_base_func(const char **filename,
   svn_stream_t *temp_stream;
   svn_error_t *err;
 
-  local_abspath = apr_hash_get(scb->relpath_map, path, APR_HASH_KEY_STRING);
+  local_abspath = svn_hash_gets(scb->relpath_map, path);
   if (!local_abspath)
     {
       *filename = NULL;

Modified: subversion/branches/verify-keep-going/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_delta/compat.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_delta/compat.c Fri Apr  5 05:29:29 2013
@@ -205,8 +205,7 @@ static struct change_node *
 locate_change(struct ev2_edit_baton *eb,
               const char *relpath)
 {
-  struct change_node *change = apr_hash_get(eb->changes, relpath,
-                                            APR_HASH_KEY_STRING);
+  struct change_node *change = svn_hash_gets(eb->changes, relpath);
 
   if (change != NULL)
     return change;
@@ -220,7 +219,7 @@ locate_change(struct ev2_edit_baton *eb,
   change->changing = SVN_INVALID_REVNUM;
   change->deleting = SVN_INVALID_REVNUM;
 
-  apr_hash_set(eb->changes, relpath, APR_HASH_KEY_STRING, change);
+  svn_hash_sets(eb->changes, relpath, change);
 
   return change;
 }
@@ -270,11 +269,11 @@ apply_propedit(struct ev2_edit_baton *eb
     }
 
   if (value == NULL)
-    apr_hash_set(change->props, name, APR_HASH_KEY_STRING, NULL);
+    svn_hash_sets(change->props, name, NULL);
   else
-    apr_hash_set(change->props,
-                 apr_pstrdup(eb->edit_pool, name), APR_HASH_KEY_STRING,
-                 svn_string_dup(value, eb->edit_pool));
+    svn_hash_sets(change->props,
+                  apr_pstrdup(eb->edit_pool, name),
+                  svn_string_dup(value, eb->edit_pool));
 
   return SVN_NO_ERROR;
 }
@@ -462,9 +461,8 @@ run_ev2_actions(struct ev2_edit_baton *e
       const char *repos_relpath = APR_ARRAY_IDX(eb->path_order,
                                                 eb->paths_processed,
                                                 const char *);
-      const struct change_node *change = apr_hash_get(eb->changes,
-                                                      repos_relpath,
-                                                      APR_HASH_KEY_STRING);
+      const struct change_node *change = svn_hash_gets(eb->changes,
+                                                       repos_relpath);
 
       svn_pool_clear(iterpool);
 
@@ -1037,7 +1035,7 @@ insert_change(const char *relpath,
   apr_pool_t *result_pool;
   struct change_node *change;
 
-  change = apr_hash_get(changes, relpath, APR_HASH_KEY_STRING);
+  change = svn_hash_gets(changes, relpath);
   if (change != NULL)
     return change;
 
@@ -1048,9 +1046,7 @@ insert_change(const char *relpath,
   change->changing = SVN_INVALID_REVNUM;
   change->deleting = SVN_INVALID_REVNUM;
 
-  apr_hash_set(changes,
-               apr_pstrdup(result_pool, relpath), APR_HASH_KEY_STRING,
-               change);
+  svn_hash_sets(changes, apr_pstrdup(result_pool, relpath), change);
 
   return change;
 }
@@ -1574,7 +1570,7 @@ apply_change(void **dir_baton,
   *dir_baton = NULL;
 
   relpath = svn_relpath_join(eb->base_relpath, ev1_relpath, scratch_pool);
-  change = apr_hash_get(eb->changes, relpath, APR_HASH_KEY_STRING);
+  change = svn_hash_gets(eb->changes, relpath);
 
   /* The callback should only be called for paths in CHANGES.  */
   SVN_ERR_ASSERT(change != NULL);

Modified: subversion/branches/verify-keep-going/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_delta/editor.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_delta/editor.c Fri Apr  5 05:29:29 2013
@@ -110,19 +110,16 @@ static const int marker_added_dir = 0;
 #define SHOULD_NOT_BE_FINISHED(editor)  SVN_ERR_ASSERT(!(editor)->finished)
 
 #define CLEAR_INCOMPLETE(editor, relpath) \
-  apr_hash_set((editor)->pending_incomplete_children, relpath,  \
-               APR_HASH_KEY_STRING, NULL);
+  svn_hash_sets((editor)->pending_incomplete_children, relpath, NULL);
 
 #define MARK_RELPATH(editor, relpath, value) \
-  apr_hash_set((editor)->completed_nodes, \
-               apr_pstrdup((editor)->state_pool, relpath), \
-               APR_HASH_KEY_STRING, value)
+  svn_hash_sets((editor)->completed_nodes, \
+                apr_pstrdup((editor)->state_pool, relpath), value)
 
 #define MARK_COMPLETED(editor, relpath) \
   MARK_RELPATH(editor, relpath, MARKER_DONE)
 #define SHOULD_NOT_BE_COMPLETED(editor, relpath) \
-  SVN_ERR_ASSERT(apr_hash_get((editor)->completed_nodes, relpath, \
-                              APR_HASH_KEY_STRING) == NULL)
+  SVN_ERR_ASSERT(svn_hash_gets((editor)->completed_nodes, relpath) == NULL)
 
 #define MARK_ALLOW_ADD(editor, relpath) \
   MARK_RELPATH(editor, relpath, MARKER_ALLOW_ADD)
@@ -148,10 +145,10 @@ static const int marker_added_dir = 0;
 /* If the parent is MARKER_ALLOW_ADD, then it has been moved-away, and we
    know it does not exist. All other cases: it might exist.  */
 #define VERIFY_PARENT_MAY_EXIST(editor, relpath) \
-  SVN_ERR_ASSERT(apr_hash_get((editor)->completed_nodes, \
-                              svn_relpath_dirname(relpath, \
-                                                  (editor)->scratch_pool), \
-                              APR_HASH_KEY_STRING) != MARKER_ALLOW_ADD)
+  SVN_ERR_ASSERT(svn_hash_gets((editor)->completed_nodes, \
+                               svn_relpath_dirname(relpath, \
+                                                   (editor)->scratch_pool)) \
+                 != MARKER_ALLOW_ADD)
 
 /* If the parent is MARKER_ADDED_DIR, then we should not be deleting
    children(*). If the parent is MARKER_ALLOW_ADD, then it has been
@@ -175,8 +172,7 @@ allow_either(const svn_editor_t *editor,
              const void *marker1,
              const void *marker2)
 {
-  void *value = apr_hash_get(editor->completed_nodes, relpath,
-                             APR_HASH_KEY_STRING);
+  void *value = svn_hash_gets(editor->completed_nodes, relpath);
   return value == marker1 || value == marker2;
 }
 
@@ -187,14 +183,13 @@ check_unknown_child(const svn_editor_t *
   const char *parent;
 
   /* If we already know about the new child, then exit early.  */
-  if (apr_hash_get(editor->pending_incomplete_children, relpath,
-                   APR_HASH_KEY_STRING) != NULL)
+  if (svn_hash_gets(editor->pending_incomplete_children, relpath) != NULL)
     return TRUE;
 
   parent = svn_relpath_dirname(relpath, editor->scratch_pool);
 
   /* Was this parent created via svn_editor_add_directory() ?  */
-  if (apr_hash_get(editor->completed_nodes, parent, APR_HASH_KEY_STRING)
+  if (svn_hash_gets(editor->completed_nodes, parent)
       == MARKER_ADDED_DIR)
     {
       /* Whoops. This child should have been listed in that add call,
@@ -211,8 +206,7 @@ mark_parent_stable(const svn_editor_t *e
                    const char *relpath)
 {
   const char *parent = svn_relpath_dirname(relpath, editor->scratch_pool);
-  const void *marker = apr_hash_get(editor->completed_nodes,
-                                    parent, APR_HASH_KEY_STRING);
+  const void *marker = svn_hash_gets(editor->completed_nodes, parent);
 
   /* If RELPATH has already been marked (to disallow adds, or that it
      has been fully-completed), then do nothing.  */
@@ -511,8 +505,7 @@ svn_editor_add_directory(svn_editor_t *e
         const char *child = svn_relpath_join(relpath, child_basename,
                                              editor->state_pool);
 
-        apr_hash_set(editor->pending_incomplete_children, child,
-                     APR_HASH_KEY_STRING, "");
+        svn_hash_sets(editor->pending_incomplete_children, child, "");
       }
   }
 #endif

Modified: subversion/branches/verify-keep-going/subversion/libsvn_delta/xdelta.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_delta/xdelta.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_delta/xdelta.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_delta/xdelta.c Fri Apr  5 05:29:29 2013
@@ -27,6 +27,7 @@
 #include <apr_general.h>        /* for APR_INLINE */
 #include <apr_hash.h>
 
+#include "svn_hash.h"
 #include "svn_delta.h"
 #include "delta.h"
 

Modified: subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_file.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_diff/diff_file.c Fri Apr  5 05:29:29 2013
@@ -544,6 +544,13 @@ find_identical_suffix(apr_off_t *suffix_
       file_for_suffix[i].chunk =
         (int) offset_to_chunk(file_for_suffix[i].size); /* last chunk */
       length[i] = offset_in_chunk(file_for_suffix[i].size);
+      if (length[i] == 0)
+        {
+          /* last chunk is an empty chunk -> start at next-to-last chunk */
+          file_for_suffix[i].chunk = file_for_suffix[i].chunk - 1;
+          length[i] = CHUNK_SIZE;
+        }
+
       if (file_for_suffix[i].chunk == file[i].chunk)
         {
           /* Prefix ended in last chunk, so we can reuse the prefix buffer */

Modified: subversion/branches/verify-keep-going/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_diff/parse-diff.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_diff/parse-diff.c Fri Apr  5 05:29:29 2013
@@ -25,6 +25,7 @@
 #include <stddef.h>
 #include <string.h>
 
+#include "svn_hash.h"
 #include "svn_types.h"
 #include "svn_error.h"
 #include "svn_io.h"
@@ -1110,8 +1111,7 @@ add_property_hunk(svn_patch_t *patch, co
 {
   svn_prop_patch_t *prop_patch;
 
-  prop_patch = apr_hash_get(patch->prop_patches, prop_name,
-                            APR_HASH_KEY_STRING);
+  prop_patch = svn_hash_gets(patch->prop_patches, prop_name);
 
   if (! prop_patch)
     {
@@ -1121,8 +1121,7 @@ add_property_hunk(svn_patch_t *patch, co
       prop_patch->hunks = apr_array_make(result_pool, 1,
                                          sizeof(svn_diff_hunk_t *));
 
-      apr_hash_set(patch->prop_patches, prop_name, APR_HASH_KEY_STRING,
-                   prop_patch);
+      svn_hash_sets(patch->prop_patches, prop_name, prop_patch);
     }
 
   APR_ARRAY_PUSH(prop_patch->hunks, svn_diff_hunk_t *) = hunk;

Modified: subversion/branches/verify-keep-going/subversion/libsvn_diff/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_diff/util.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_diff/util.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_diff/util.c Fri Apr  5 05:29:29 2013
@@ -25,6 +25,7 @@
 #include <apr.h>
 #include <apr_general.h>
 
+#include "svn_hash.h"
 #include "svn_pools.h"
 #include "svn_dirent_uri.h"
 #include "svn_props.h"
@@ -504,8 +505,7 @@ svn_diff__display_prop_diffs(svn_stream_
         = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
 
       if (original_props)
-        original_value = apr_hash_get(original_props,
-                                      propchange->name, APR_HASH_KEY_STRING);
+        original_value = svn_hash_gets(original_props, propchange->name);
       else
         original_value = NULL;
 

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs/access.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs/access.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs/access.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs/access.c Fri Apr  5 05:29:29 2013
@@ -24,6 +24,7 @@
 
 #include <apr_hash.h>
 
+#include "svn_hash.h"
 #include "svn_types.h"
 #include "svn_pools.h"
 #include "svn_fs.h"
@@ -86,8 +87,7 @@ svn_fs_access_add_lock_token2(svn_fs_acc
                               const char *path,
                               const char *token)
 {
-  apr_hash_set(access_ctx->lock_tokens,
-               token, APR_HASH_KEY_STRING, path);
+  svn_hash_sets(access_ctx->lock_tokens, token, path);
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs/editor.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs/editor.c Fri Apr  5 05:29:29 2013
@@ -28,6 +28,7 @@
 #include "svn_pools.h"
 #include "svn_fs.h"
 #include "svn_props.h"
+#include "svn_path.h"
 
 #include "svn_private_config.h"
 

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.c?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.c Fri Apr  5 05:29:29 2013
@@ -30,6 +30,7 @@
 #include <apr_uuid.h>
 #include <apr_strings.h>
 
+#include "svn_hash.h"
 #include "svn_ctype.h"
 #include "svn_types.h"
 #include "svn_dso.h"
@@ -48,7 +49,6 @@
 #include "private/svn_subr_private.h"
 
 #include "fs-loader.h"
-#include "svn_hash.h"
 
 /* This is defined by configure on platforms which use configure, but
    we need to define a fallback for Windows. */
@@ -451,6 +451,8 @@ svn_fs_create(svn_fs_t **fs_p, const cha
 
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
                        vtable->create(*fs_p, path, pool, common_pool));
+  SVN_ERR(vtable->set_svn_fs_open(*fs_p, svn_fs_open));
+
   return SVN_NO_ERROR;
 }
 
@@ -464,6 +466,8 @@ svn_fs_open(svn_fs_t **fs_p, const char 
   *fs_p = fs_new(fs_config, pool);
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
                        vtable->open_fs(*fs_p, path, pool, common_pool));
+  SVN_ERR(vtable->set_svn_fs_open(*fs_p, svn_fs_open));
+
   return SVN_NO_ERROR;
 }
 
@@ -629,11 +633,11 @@ svn_fs_recover(const char *path,
 }
 
 svn_error_t *
-svn_fs_verify_rev(svn_fs_t *fs,
-                  svn_revnum_t revision,
-                  apr_pool_t *scratch_pool)
+svn_fs_verify_root(svn_fs_root_t *root,
+                   apr_pool_t *scratch_pool)
 {
-  SVN_ERR(fs->vtable->verify_rev(fs, revision, scratch_pool));
+  svn_fs_t *fs = root->fs;
+  SVN_ERR(fs->vtable->verify_root(root, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -666,6 +670,8 @@ svn_fs_create_berkeley(svn_fs_t *fs, con
   /* Perform the actual creation. */
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
                        vtable->create(fs, path, fs->pool, common_pool));
+  SVN_ERR(vtable->set_svn_fs_open(fs, svn_fs_open));
+
   return SVN_NO_ERROR;
 }
 
@@ -677,6 +683,8 @@ svn_fs_open_berkeley(svn_fs_t *fs, const
   SVN_ERR(fs_library_vtable(&vtable, path, fs->pool));
   SVN_MUTEX__WITH_LOCK(common_pool_lock,
                        vtable->open_fs(fs, path, fs->pool, common_pool));
+  SVN_ERR(vtable->set_svn_fs_open(fs, svn_fs_open));
+
   return SVN_NO_ERROR;
 }
 
@@ -750,16 +758,10 @@ svn_fs_commit_txn(const char **conflict_
                   svn_fs_txn_t *txn, apr_pool_t *pool)
 {
   svn_error_t *err;
-#ifdef PACK_AFTER_EVERY_COMMIT
-  svn_fs_root_t *txn_root;
-  svn_fs_t *fs;
-  const char *fs_path;
 
   *new_rev = SVN_INVALID_REVNUM;
-  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
-  fs = svn_fs_root_fs(txn_root);
-  fs_path = svn_fs_path(fs, pool);
-#endif
+  if (conflict_p)
+    *conflict_p = NULL;
 
   err = txn->vtable->commit(conflict_p, new_rev, txn, pool);
 
@@ -779,6 +781,8 @@ svn_fs_commit_txn(const char **conflict_
 
 #ifdef PACK_AFTER_EVERY_COMMIT
   {
+    svn_fs_t *fs = txn->fs;
+    const char *fs_path = svn_fs_path(fs, pool);
     err = svn_fs_pack(fs_path, NULL, NULL, NULL, NULL, pool);
     if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
       /* Pre-1.6 filesystem. */

Modified: subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.h?rev=1464833&r1=1464832&r2=1464833&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/verify-keep-going/subversion/libsvn_fs/fs-loader.h Fri Apr  5 05:29:29 2013
@@ -124,6 +124,14 @@ typedef struct fs_library_vtable_t
      into the FS vtable. */
   svn_fs_id_t *(*parse_id)(const char *data, apr_size_t len,
                            apr_pool_t *pool);
+  /* Allow an FSAP to call svn_fs_open(), which is in a higher-level library
+     (libsvn_fs-1.so) and cannot easily be moved to libsvn_fs_util. */
+  svn_error_t *(*set_svn_fs_open)(svn_fs_t *fs,
+                                  svn_error_t *(*svn_fs_open_)(svn_fs_t **,
+                                                               const char *,
+                                                               apr_hash_t *,
+                                                               apr_pool_t *));
+
 } fs_library_vtable_t;
 
 /* This is the type of symbol an FS module defines to fetch the
@@ -204,9 +212,8 @@ typedef struct fs_vtable_t
                             svn_fs_get_locks_callback_t get_locks_func,
                             void *get_locks_baton,
                             apr_pool_t *pool);
-  svn_error_t *(*verify_rev)(svn_fs_t *fs,
-                             svn_revnum_t revision,
-                             apr_pool_t *pool);
+  svn_error_t *(*verify_root)(svn_fs_root_t *root,
+                              apr_pool_t *pool);
   svn_error_t *(*freeze)(svn_fs_t *fs,
                          svn_error_t *(*freeze_body)(void *, apr_pool_t *),
                          void *baton, apr_pool_t *pool);