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/03/18 10:35:29 UTC

svn commit: r1457684 [18/22] - in /subversion/branches/verify-keep-going: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ notes/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subv...

Modified: subversion/branches/verify-keep-going/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/cl.h?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/cl.h (original)
+++ subversion/branches/verify-keep-going/subversion/svn/cl.h Mon Mar 18 09:35:24 2013
@@ -344,10 +344,16 @@ svn_cl__get_conflict_func_interactive_ba
   void *cancel_baton,
   apr_pool_t *result_pool);
 
-/* A conflict-resolution callback which prompts the user to choose
-   one of the 3 fulltexts, edit the merged file on the spot, or just
-   skip the conflict (to be resolved later).
-   Implements @c svn_wc_conflict_resolver_func_t. */
+/* A callback capable of doing interactive conflict resolution.
+
+   The BATON must come from svn_cl__get_conflict_func_interactive_baton().
+   Resolves based on the --accept option if one was given to that function,
+   otherwise prompts the user to choose one of the three fulltexts, edit
+   the merged file on the spot, or just skip the conflict (to be resolved
+   later), among other options.
+
+   Implements svn_wc_conflict_resolver_func2_t.
+ */
 svn_error_t *
 svn_cl__conflict_func_interactive(svn_wc_conflict_result_t **result,
                                   const svn_wc_conflict_description2_t *desc,
@@ -374,15 +380,20 @@ svn_cl__conflict_func_postpone(svn_wc_co
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 
-/* Perform conflict resolver on any conflicted paths stored in the BATON
+/* Perform conflict resolution on any conflicted paths stored in the BATON
  * which was obtained from svn_cl__get_conflict_func_postpone_baton().
  *
+ * If CONFLICTS_ALL_RESOLVED is not null, set *CONFLICTS_ALL_RESOLVED to
+ * true if this resolves all the conflicts on the paths that were
+ * recorded (or if none were recorded); or to false if some conflicts
+ * remain.
+ *
  * The conflict resolution will be interactive if ACCEPT_WHICH is
  * svn_cl__accept_unspecified.
  */
 svn_error_t *
-svn_cl__resolve_postponed_conflicts(void *baton,
-                                    svn_depth_t depth,
+svn_cl__resolve_postponed_conflicts(svn_boolean_t *conflicts_all_resolved,
+                                    void *baton,
                                     svn_cl__accept_t accept_which,
                                     const char *editor_cmd,
                                     svn_client_ctx_t *ctx,
@@ -578,13 +589,20 @@ svn_cl__check_externals_failed_notify_wr
                                               const svn_wc_notify_t *n,
                                               apr_pool_t *pool);
 
-/* Print conflict stats accumulated in NOTIFY_BATON.
+/* Reset to zero the conflict stats accumulated in BATON, which is the
+ * notifier baton from svn_cl__get_notifier().
+ */
+svn_error_t *
+svn_cl__notifier_reset_conflict_stats(void *baton);
+
+/* Print the conflict stats accumulated in BATON, which is the
+ * notifier baton from svn_cl__get_notifier().
  * Return any error encountered during printing.
- * Do all allocations in POOL.*/
+ */
 svn_error_t *
-svn_cl__print_conflict_stats(void *notify_baton, apr_pool_t *pool);
+svn_cl__notifier_print_conflict_stats(void *baton, apr_pool_t *scratch_pool);
+
 
-
 /*** Log message callback stuffs. ***/
 
 /* Allocate in POOL a baton for use with svn_cl__get_log_message().

Modified: subversion/branches/verify-keep-going/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/conflict-callbacks.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/conflict-callbacks.c Mon Mar 18 09:35:24 2013
@@ -52,6 +52,7 @@ struct svn_cl__interactive_conflict_bato
   svn_boolean_t external_failed;
   svn_cmdline_prompt_baton_t *pb;
   const char *path_prefix;
+  svn_boolean_t quit;
 };
 
 svn_error_t *
@@ -75,6 +76,7 @@ svn_cl__get_conflict_func_interactive_ba
   (*b)->external_failed = FALSE;
   (*b)->pb = pb;
   SVN_ERR(svn_dirent_get_absolute(&(*b)->path_prefix, "", result_pool));
+  (*b)->quit = FALSE;
 
   return SVN_NO_ERROR;
 }
@@ -319,25 +321,25 @@ static const resolver_option_t text_conf
   { "df", "diff-full",        N_("show all changes made to merged file"), -1 },
   { "r",  "resolved",         N_("accept merged version of file"),
                               svn_wc_conflict_choose_merged },
-  { "" },
+  { "",   "",                 "", svn_wc_conflict_choose_unspecified },
   { "dc", "display-conflict", N_("show all conflicts (ignoring merged version)"), -1 },
   { "mc", "mine-conflict",    N_("accept my version for all conflicts (same)"),
                               svn_wc_conflict_choose_mine_conflict },
   { "tc", "theirs-conflict",  N_("accept their version for all conflicts (same)"),
                               svn_wc_conflict_choose_theirs_conflict },
-  { "" },
+  { "",   "",                 "", svn_wc_conflict_choose_unspecified },
   { "mf", "mine-full",        N_("accept my version of entire file (even "
                                  "non-conflicts)"),
                               svn_wc_conflict_choose_mine_full },
   { "tf", "theirs-full",      N_("accept their version of entire file (same)"),
                               svn_wc_conflict_choose_theirs_full },
-  { "" },
+  { "",   "",                 "", svn_wc_conflict_choose_unspecified },
   { "p",  "postpone",         N_("mark the conflict to be resolved later"),
                               svn_wc_conflict_choose_postpone },
   { "m",  "merge",            N_("use internal merge tool to resolve conflict"), -1 },
   { "l",  "launch",           N_("launch external tool to resolve conflict"), -1 },
   { "q",  "quit",             N_("postpone all remaining conflicts"),
-                              svn_cl__accept_postpone },
+                              svn_wc_conflict_choose_postpone },
   { "s",  "show all options", N_("show this list (also 'h', '?')"), -1 },
   { NULL }
 };
@@ -353,7 +355,7 @@ static const resolver_option_t prop_conf
   { "tf", "theirs-full",      N_("accept their version of entire file (same)"),
                               svn_wc_conflict_choose_theirs_full },
   { "q",  "quit",             N_("postpone all remaining conflicts"),
-                              svn_cl__accept_postpone },
+                              svn_wc_conflict_choose_postpone },
   { "h",  "help",             N_("show this help (also '?')"), -1 },
   { NULL }
 };
@@ -368,7 +370,7 @@ static const resolver_option_t obstructe
   { "tf", "theirs-full",      N_("accept incoming item (overwrite pre-existing item)"),
                               svn_wc_conflict_choose_theirs_full },
   { "q",  "quit",             N_("postpone all remaining conflicts"),
-                              svn_cl__accept_postpone },
+                              svn_wc_conflict_choose_postpone },
   { "h",  "help",             N_("show this help (also '?')"), -1 },
   { NULL }
 };
@@ -380,12 +382,8 @@ static const resolver_option_t tree_conf
                               svn_wc_conflict_choose_postpone },
   { "r",  "resolved",         N_("accept current working copy state"),
                               svn_wc_conflict_choose_merged },
-  { "mc", "mine-conflict",    N_("prefer local change"),
-                              svn_wc_conflict_choose_mine_conflict },
-  { "tc", "theirs-conflict",  N_("prefer incoming change"),
-                              svn_wc_conflict_choose_theirs_conflict },
   { "q",  "quit",             N_("postpone all remaining conflicts"),
-                              svn_cl__accept_postpone },
+                              svn_wc_conflict_choose_postpone },
   { "h",  "help",             N_("show this help (also '?')"), -1 },
   { NULL }
 };
@@ -394,17 +392,47 @@ static const resolver_option_t tree_conf
 {
   { "p",  "postpone",         N_("resolve the conflict later"),
                               svn_wc_conflict_choose_postpone },
-  { "mc", "mine-conflict",    N_("apply the update to the move destination"),
+  { "mc", "mine-conflict",    N_("apply update to the move destination"),
                               svn_wc_conflict_choose_mine_conflict },
-  { "tc", "theirs-conflict",  N_("break the move, change move destination into "
-                                 "a copy"),
-                              svn_wc_conflict_choose_theirs_conflict },
+  { "r",  "resolved",         N_("mark resolved (the move will become a copy)"),
+                              svn_wc_conflict_choose_merged },
+  { "q",  "quit",             N_("postpone all remaining conflicts"),
+                              svn_wc_conflict_choose_postpone },
+  { "h",  "help",             N_("show this help (also '?')"), -1 },
+  { NULL }
+};
+
+static const resolver_option_t tree_conflict_options_update_deleted[] =
+{
+  { "p",  "postpone",         N_("resolve the conflict later"),
+                              svn_wc_conflict_choose_postpone },
+  { "mc", "mine-conflict",    N_("keep any moves affected by this deletion"),
+                              svn_wc_conflict_choose_mine_conflict },
+  { "r",  "resolved",         N_("mark resolved (any affected moves will "
+                                 "become copies)"),
+                              svn_wc_conflict_choose_merged },
+  { "q",  "quit",             N_("postpone all remaining conflicts"),
+                              svn_wc_conflict_choose_postpone },
+  { "h",  "help",             N_("show this help (also '?')"), -1 },
+  { NULL }
+};
+
+static const resolver_option_t tree_conflict_options_update_replaced[] =
+{
+  { "p",  "postpone",         N_("resolve the conflict later"),
+                              svn_wc_conflict_choose_postpone },
+  { "mc", "mine-conflict",    N_("keep any moves affected by this replacement"),
+                              svn_wc_conflict_choose_mine_conflict },
+  { "r",  "resolved",         N_("mark resolved (any affected moves will "
+                                 "become copies)"),
+                              svn_wc_conflict_choose_merged },
   { "q",  "quit",             N_("postpone all remaining conflicts"),
-                              svn_cl__accept_postpone },
+                              svn_wc_conflict_choose_postpone },
   { "h",  "help",             N_("show this help (also '?')"), -1 },
   { NULL }
 };
 
+
 /* Return a pointer to the option description in OPTIONS matching the
  * one- or two-character OPTION_CODE.  Return NULL if not found. */
 static const resolver_option_t *
@@ -415,7 +443,8 @@ find_option(const resolver_option_t *opt
 
   for (opt = options; opt->code; opt++)
     {
-      if (strcmp(opt->code, option_code) == 0)
+      /* Ignore code "" (blank lines) which is not a valid answer. */
+      if (opt->code[0] && strcmp(opt->code, option_code) == 0)
         return opt;
     }
   return NULL;
@@ -515,7 +544,12 @@ prompt_user(const resolver_option_t **op
   SVN_ERR(svn_cmdline_prompt_user2(&answer, prompt, prompt_baton, scratch_pool));
   *opt = find_option(conflict_options, answer);
 
-  if (strcmp(answer, "h") == 0 || strcmp(answer, "?") == 0)
+  if (! *opt)
+    {
+      SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                  _("Unrecognized option.\n\n")));
+    }
+  else if (strcmp(answer, "h") == 0 || strcmp(answer, "?") == 0)
     {
       SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "\n%s\n",
                                   help_string(conflict_options,
@@ -602,7 +636,8 @@ handle_text_conflict(svn_wc_conflict_res
       if (strcmp(opt->code, "q") == 0)
         {
           result->choice = opt->choice;
-          b->accept_which = opt->choice;
+          b->accept_which = svn_cl__accept_postpone;
+          b->quit = TRUE;
           break;
         }
       else if (strcmp(opt->code, "s") == 0)
@@ -687,6 +722,10 @@ handle_text_conflict(svn_wc_conflict_res
         }
       else if (strcmp(opt->code, "l") == 0 || strcmp(opt->code, ":-l") == 0)
         {
+          /* ### This check should be earlier as it's nasty to offer an option
+           *     and then when the user chooses it say 'Invalid option'. */
+          /* ### 'merged_file' shouldn't be necessary *before* we launch the
+           *     resolver: it should be the *result* of doing so. */
           if (desc->base_abspath && desc->their_abspath &&
               desc->my_abspath && desc->merged_file)
             {
@@ -717,8 +756,10 @@ handle_text_conflict(svn_wc_conflict_res
           if (result->choice == svn_wc_conflict_choose_merged
               && ! knows_something)
             {
-              SVN_ERR(svn_cmdline_fprintf(stderr, iterpool,
-                                          _("Invalid option.\n\n")));
+              SVN_ERR(svn_cmdline_fprintf(
+                        stderr, iterpool,
+                        _("Invalid option; use diff/edit/merge/launch "
+                          "before choosing 'resolved'.\n\n")));
               continue;
             }
 
@@ -797,7 +838,8 @@ handle_prop_conflict(svn_wc_conflict_res
       if (strcmp(opt->code, "q") == 0)
         {
           result->choice = opt->choice;
-          b->accept_which = opt->choice;
+          b->accept_which = svn_cl__accept_postpone;
+          b->quit = TRUE;
           break;
         }
       else if (opt->choice != -1)
@@ -842,11 +884,17 @@ handle_tree_conflict(svn_wc_conflict_res
 
       svn_pool_clear(iterpool);
 
-      if ((desc->operation == svn_wc_operation_update ||
-           desc->operation == svn_wc_operation_switch) &&
-          desc->reason == svn_wc_conflict_reason_moved_away)
+      if (desc->operation == svn_wc_operation_update ||
+          desc->operation == svn_wc_operation_switch)
         {
-          tc_opts = tree_conflict_options_update_moved_away;
+          if (desc->reason == svn_wc_conflict_reason_moved_away)
+            tc_opts = tree_conflict_options_update_moved_away;
+          else if (desc->reason == svn_wc_conflict_reason_deleted)
+            tc_opts = tree_conflict_options_update_deleted;
+          else if (desc->reason == svn_wc_conflict_reason_replaced)
+            tc_opts = tree_conflict_options_update_replaced;
+          else
+            tc_opts = tree_conflict_options;
         }
       else
         tc_opts = tree_conflict_options;
@@ -858,7 +906,8 @@ handle_tree_conflict(svn_wc_conflict_res
       if (strcmp(opt->code, "q") == 0)
         {
           result->choice = opt->choice;
-          b->accept_which = opt->choice;
+          b->accept_which = svn_cl__accept_postpone;
+          b->quit = TRUE;
           break;
         }
       else if (opt->choice != -1)
@@ -907,7 +956,8 @@ handle_obstructed_add(svn_wc_conflict_re
       if (strcmp(opt->code, "q") == 0)
         {
           result->choice = opt->choice;
-          b->accept_which = opt->choice;
+          b->accept_which = svn_cl__accept_postpone;
+          b->quit = TRUE;
           break;
         }
       else if (opt->choice != -1)
@@ -921,8 +971,6 @@ handle_obstructed_add(svn_wc_conflict_re
   return SVN_NO_ERROR;
 }
 
-/* Implement svn_wc_conflict_resolver_func2_t; resolves based on
-   --accept option if given, else by prompting. */
 svn_error_t *
 svn_cl__conflict_func_interactive(svn_wc_conflict_result_t **result,
                                   const svn_wc_conflict_description2_t *desc,
@@ -1137,9 +1185,6 @@ get_postponed_conflicted_paths(void *bat
   apr_array_header_t *result_array;
   int i;
 
-  if (apr_hash_count(conflicted_paths) == 0)
-    return NULL;
-
   sorted_array = svn_sort__hash(conflicted_paths,
                                 svn_sort_compare_items_as_paths,
                                 apr_hash_pool_get(conflicted_paths));
@@ -1158,8 +1203,8 @@ get_postponed_conflicted_paths(void *bat
 }
 
 svn_error_t *
-svn_cl__resolve_postponed_conflicts(void *baton,
-                                    svn_depth_t depth,
+svn_cl__resolve_postponed_conflicts(svn_boolean_t *conflicts_all_resolved,
+                                    void *baton,
                                     svn_cl__accept_t accept_which,
                                     const char *editor_cmd,
                                     svn_client_ctx_t *ctx,
@@ -1170,8 +1215,9 @@ svn_cl__resolve_postponed_conflicts(void
   apr_pool_t *iterpool;
 
   targets = get_postponed_conflicted_paths(baton, scratch_pool);
-  if (targets == NULL)
-    return SVN_NO_ERROR;
+
+  if (conflicts_all_resolved != NULL)
+    *conflicts_all_resolved = TRUE;
 
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < targets->nelts; i++)
@@ -1182,6 +1228,7 @@ svn_cl__resolve_postponed_conflicts(void
       svn_wc_conflict_resolver_func2_t conflict_func2;
       void *conflict_baton2;
       svn_cl__interactive_conflict_baton_t *b;
+      svn_boolean_t text_c, prop_c, tree_c;
 
       svn_pool_clear(iterpool);
 
@@ -1201,7 +1248,7 @@ svn_cl__resolve_postponed_conflicts(void
                                                           scratch_pool));
       ctx->conflict_baton2 = b;
 
-      err = svn_client_resolve(local_abspath, depth,
+      err = svn_client_resolve(local_abspath, svn_depth_empty,
                                svn_wc_conflict_choose_unspecified,
                                ctx, iterpool);
 
@@ -1217,6 +1264,19 @@ svn_cl__resolve_postponed_conflicts(void
 
           svn_error_clear(err);
         }
+
+      /* Report if we left any of the conflicts unresolved */
+      if (conflicts_all_resolved != NULL)
+        {
+          SVN_ERR(svn_wc_conflicted_p3(&text_c, &prop_c, &tree_c,
+                                       ctx->wc_ctx, local_abspath,
+                                       scratch_pool));
+          if (text_c || prop_c || tree_c)
+            *conflicts_all_resolved = FALSE;
+        }
+
+      if (b->quit)
+        break;
     }
   svn_pool_destroy(iterpool);
 

Modified: subversion/branches/verify-keep-going/subversion/svn/merge-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/merge-cmd.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/merge-cmd.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/merge-cmd.c Mon Mar 18 09:35:24 2013
@@ -140,6 +140,126 @@ automatic_merge(const char *source_path_
   return SVN_NO_ERROR;
 }
 
+/* Run a merge.
+ *
+ * (No docs yet, as this code was just hoisted out of svn_cl__merge().)
+ *
+ * Having FIRST_RANGE_START/_END params is ugly -- we should be able to use
+ * PEG_REVISION1/2 and/or RANGES_TO_MERGE instead, maybe adjusting the caller.
+ */
+static svn_error_t *
+run_merge(svn_boolean_t two_sources_specified,
+          const char *sourcepath1,
+          svn_opt_revision_t peg_revision1,
+          const char *sourcepath2,
+          const char *targetpath,
+          apr_array_header_t *ranges_to_merge,
+          svn_opt_revision_t first_range_start,
+          svn_opt_revision_t first_range_end,
+          svn_cl__opt_state_t *opt_state,
+          apr_array_header_t *options,
+          svn_client_ctx_t *ctx,
+          apr_pool_t *scratch_pool)
+{
+  svn_error_t *merge_err;
+
+  /* Do an automatic merge if just one source and no revisions. */
+  if ((! two_sources_specified)
+      && (! opt_state->reintegrate)
+      && (! opt_state->ignore_ancestry)
+      && first_range_start.kind == svn_opt_revision_unspecified
+      && first_range_end.kind == svn_opt_revision_unspecified)
+    {
+      merge_err = automatic_merge(sourcepath1, &peg_revision1, targetpath,
+                                  opt_state->depth,
+                                  FALSE /*diff_ignore_ancestry*/,
+                                  opt_state->force, /* force_delete */
+                                  opt_state->record_only,
+                                  opt_state->dry_run,
+                                  opt_state->allow_mixed_rev,
+                                  TRUE /*allow_local_mods*/,
+                                  TRUE /*allow_switched_subtrees*/,
+                                  opt_state->verbose,
+                                  options, ctx, scratch_pool);
+    }
+  else if (opt_state->reintegrate)
+    {
+      merge_err = svn_client_merge_reintegrate(
+                    sourcepath1, &peg_revision1, targetpath,
+                    opt_state->dry_run, options, ctx, scratch_pool);
+    }
+  else if (! two_sources_specified)
+    {
+      /* If we don't have at least one valid revision range, pick a
+         good one that spans the entire set of revisions on our
+         source. */
+      if ((first_range_start.kind == svn_opt_revision_unspecified)
+          && (first_range_end.kind == svn_opt_revision_unspecified))
+        {
+          svn_opt_revision_range_t *range = apr_pcalloc(scratch_pool,
+                                                        sizeof(*range));
+          ranges_to_merge = apr_array_make(scratch_pool, 1, sizeof(range));
+          range->start.kind = svn_opt_revision_number;
+          range->start.value.number = 1;
+          range->end = peg_revision1;
+          APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *) = range;
+
+          /* This must be a 'sync' merge so check branch relationship. */
+          if (opt_state->verbose)
+            SVN_ERR(svn_cmdline_printf(
+                      scratch_pool, _("--- Checking branch relationship\n")));
+          SVN_ERR_W(svn_cl__check_related_source_and_target(
+                      sourcepath1, &peg_revision1,
+                      targetpath, &unspecified_revision, ctx, scratch_pool),
+                _("Source and target must be different but related branches"));
+        }
+
+      if (opt_state->verbose)
+        SVN_ERR(svn_cmdline_printf(scratch_pool, _("--- Merging\n")));
+      merge_err = svn_client_merge_peg5(sourcepath1,
+                                        ranges_to_merge,
+                                        &peg_revision1,
+                                        targetpath,
+                                        opt_state->depth,
+                                        opt_state->ignore_ancestry,
+                                        opt_state->ignore_ancestry,
+                                        opt_state->force, /* force_delete */
+                                        opt_state->record_only,
+                                        opt_state->dry_run,
+                                        opt_state->allow_mixed_rev,
+                                        options,
+                                        ctx,
+                                        scratch_pool);
+    }
+  else
+    {
+      if (svn_path_is_url(sourcepath1) != svn_path_is_url(sourcepath2))
+        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                _("Merge sources must both be "
+                                  "either paths or URLs"));
+
+      if (opt_state->verbose)
+        SVN_ERR(svn_cmdline_printf(scratch_pool, _("--- Merging\n")));
+      merge_err = svn_client_merge5(sourcepath1,
+                                    &first_range_start,
+                                    sourcepath2,
+                                    &first_range_end,
+                                    targetpath,
+                                    opt_state->depth,
+                                    opt_state->ignore_ancestry,
+                                    opt_state->ignore_ancestry,
+                                    opt_state->force, /* force_delete */
+                                    opt_state->record_only,
+                                    opt_state->dry_run,
+                                    opt_state->allow_mixed_rev,
+                                    options,
+                                    ctx,
+                                    scratch_pool);
+    }
+
+  return merge_err;
+}
+
 /* This implements the `svn_opt_subcommand_t' interface. */
 svn_error_t *
 svn_cl__merge(apr_getopt_t *os,
@@ -151,8 +271,7 @@ svn_cl__merge(apr_getopt_t *os,
   apr_array_header_t *targets;
   const char *sourcepath1 = NULL, *sourcepath2 = NULL, *targetpath = "";
   svn_boolean_t two_sources_specified = TRUE;
-  svn_error_t *err = SVN_NO_ERROR;
-  svn_error_t *merge_err = SVN_NO_ERROR;
+  svn_error_t *merge_err;
   svn_opt_revision_t first_range_start, first_range_end, peg_revision1,
     peg_revision2;
   apr_array_header_t *options, *ranges_to_merge = opt_state->revision_ranges;
@@ -447,125 +566,38 @@ svn_cl__merge(apr_getopt_t *os,
       ctx->conflict_baton2 = b;
     }
 
-  /* Do an automatic merge if just one source and no revisions. */
-  if ((! two_sources_specified)
-      && (! opt_state->reintegrate)
-      && (! opt_state->ignore_ancestry)
-      && first_range_start.kind == svn_opt_revision_unspecified
-      && first_range_end.kind == svn_opt_revision_unspecified)
-    {
-      merge_err = automatic_merge(sourcepath1, &peg_revision1, targetpath,
-                                  opt_state->depth,
-                                  FALSE /*diff_ignore_ancestry*/,
-                                  opt_state->force, /* force_delete */
-                                  opt_state->record_only,
-                                  opt_state->dry_run,
-                                  opt_state->allow_mixed_rev,
-                                  TRUE /*allow_local_mods*/,
-                                  TRUE /*allow_switched_subtrees*/,
-                                  opt_state->verbose,
-                                  options, ctx, pool);
-    }
-  else if (opt_state->reintegrate)
-    {
-      merge_err = svn_client_merge_reintegrate(
-                    sourcepath1, &peg_revision1, targetpath,
-                    opt_state->dry_run, options, ctx, pool);
-    }
-  else if (! two_sources_specified)
-    {
-      /* If we don't have at least one valid revision range, pick a
-         good one that spans the entire set of revisions on our
-         source. */
-      if ((first_range_start.kind == svn_opt_revision_unspecified)
-          && (first_range_end.kind == svn_opt_revision_unspecified))
-        {
-          svn_opt_revision_range_t *range = apr_pcalloc(pool, sizeof(*range));
-          ranges_to_merge = apr_array_make(pool, 1, sizeof(range));
-          range->start.kind = svn_opt_revision_number;
-          range->start.value.number = 1;
-          range->end = peg_revision1;
-          APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *) = range;
-
-          /* This must be a 'sync' merge so check branch relationship. */
-          if (opt_state->verbose)
-            SVN_ERR(svn_cmdline_printf(pool, _("--- Checking branch relationship\n")));
-          SVN_ERR_W(svn_cl__check_related_source_and_target(
-                      sourcepath1, &peg_revision1,
-                      targetpath, &unspecified_revision, ctx, pool),
-                _("Source and target must be different but related branches"));
-        }
-
-      if (opt_state->verbose)
-        SVN_ERR(svn_cmdline_printf(pool, _("--- Merging\n")));
-      merge_err = svn_client_merge_peg5(sourcepath1,
-                                        ranges_to_merge,
-                                        &peg_revision1,
-                                        targetpath,
-                                        opt_state->depth,
-                                        opt_state->ignore_ancestry,
-                                        opt_state->ignore_ancestry,
-                                        opt_state->force, /* force_delete */
-                                        opt_state->record_only,
-                                        opt_state->dry_run,
-                                        opt_state->allow_mixed_rev,
-                                        options,
-                                        ctx,
-                                        pool);
-    }
-  else
-    {
-      if (svn_path_is_url(sourcepath1) != svn_path_is_url(sourcepath2))
-        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                _("Merge sources must both be "
-                                  "either paths or URLs"));
-
-      if (opt_state->verbose)
-        SVN_ERR(svn_cmdline_printf(pool, _("--- Merging\n")));
-      merge_err = svn_client_merge5(sourcepath1,
-                                    &first_range_start,
-                                    sourcepath2,
-                                    &first_range_end,
-                                    targetpath,
-                                    opt_state->depth,
-                                    opt_state->ignore_ancestry,
-                                    opt_state->ignore_ancestry,
-                                    opt_state->force, /* force_delete */
-                                    opt_state->record_only,
-                                    opt_state->dry_run,
-                                    opt_state->allow_mixed_rev,
-                                    options,
-                                    ctx,
-                                    pool);
-    }
-
-  if (! opt_state->quiet)
-    err = svn_cl__print_conflict_stats(ctx->notify_baton2, pool);
-
-  /* Resolve any postponed conflicts.  (Only if we've been using the
-   * default 'postpone' resolver which remembers what was postponed.) */
-  if (!err && ctx->conflict_func2 == svn_cl__conflict_func_postpone)
-    err = svn_cl__resolve_postponed_conflicts(ctx->conflict_baton2,
-                                              opt_state->depth,
-                                              opt_state->accept_which,
-                                              opt_state->editor_cmd,
-                                              ctx, pool);
-  if (merge_err)
-    {
-      if (merge_err->apr_err ==
-          SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING)
-        {
-          err = svn_error_quick_wrap(
-            svn_error_compose_create(merge_err, err),
-            _("Merge tracking not possible, use --ignore-ancestry or\n"
-              "fix invalid mergeinfo in target with 'svn propset'"));
-        }
-      else
-        {
-          err = svn_error_compose_create(merge_err, err);
-          return svn_cl__may_need_force(err);
-        }
+  merge_err = run_merge(two_sources_specified,
+                        sourcepath1, peg_revision1,
+                        sourcepath2,
+                        targetpath,
+                        ranges_to_merge, first_range_start, first_range_end,
+                        opt_state, options, ctx, pool);
+  if (merge_err && merge_err->apr_err
+                   == SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING)
+    {
+      return svn_error_quick_wrap(
+               merge_err,
+               _("Merge tracking not possible, use --ignore-ancestry or\n"
+                 "fix invalid mergeinfo in target with 'svn propset'"));
+    }
+  if (! merge_err || merge_err->apr_err == SVN_ERR_WC_FOUND_CONFLICT)
+    {
+      svn_error_t *err = SVN_NO_ERROR;
+
+      if (! opt_state->quiet)
+        err = svn_cl__notifier_print_conflict_stats(ctx->notify_baton2,
+                                                        pool);
+
+      /* Resolve any postponed conflicts.  (Only if we've been using the
+       * default 'postpone' resolver which remembers what was postponed.) */
+      if (!err && ctx->conflict_func2 == svn_cl__conflict_func_postpone)
+        err = svn_cl__resolve_postponed_conflicts(NULL,
+                                                  ctx->conflict_baton2,
+                                                  opt_state->accept_which,
+                                                  opt_state->editor_cmd,
+                                                  ctx, pool);
+      merge_err = svn_error_compose_create(merge_err, err);
     }
 
-  return svn_error_trace(err);
+  return svn_cl__may_need_force(merge_err);
 }

Modified: subversion/branches/verify-keep-going/subversion/svn/notify.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/notify.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/notify.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/notify.c Mon Mar 18 09:35:24 2013
@@ -54,10 +54,10 @@ struct notify_baton
                                     when we've already had one print error. */
 
   /* Conflict stats for update and merge. */
-  unsigned int text_conflicts;
-  unsigned int prop_conflicts;
-  unsigned int tree_conflicts;
-  unsigned int skipped_paths;
+  int text_conflicts;
+  int prop_conflicts;
+  int tree_conflicts;
+  int skipped_paths;
 
   /* The cwd, for use in decomposing absolute paths. */
   const char *path_prefix;
@@ -65,38 +65,43 @@ struct notify_baton
 
 
 svn_error_t *
-svn_cl__print_conflict_stats(void *notify_baton, apr_pool_t *pool)
+svn_cl__notifier_reset_conflict_stats(void *baton)
 {
-  struct notify_baton *nb = notify_baton;
-  unsigned int text_conflicts;
-  unsigned int prop_conflicts;
-  unsigned int tree_conflicts;
-  unsigned int skipped_paths;
-
-  text_conflicts = nb->text_conflicts;
-  prop_conflicts = nb->prop_conflicts;
-  tree_conflicts = nb->tree_conflicts;
-  skipped_paths = nb->skipped_paths;
-
-  if (text_conflicts > 0 || prop_conflicts > 0
-    || tree_conflicts > 0 || skipped_paths > 0)
-      SVN_ERR(svn_cmdline_printf(pool, "%s", _("Summary of conflicts:\n")));
-
-  if (text_conflicts > 0)
-    SVN_ERR(svn_cmdline_printf
-      (pool, _("  Text conflicts: %u\n"), text_conflicts));
-
-  if (prop_conflicts > 0)
-    SVN_ERR(svn_cmdline_printf
-      (pool, _("  Property conflicts: %u\n"), prop_conflicts));
-
-  if (tree_conflicts > 0)
-    SVN_ERR(svn_cmdline_printf
-      (pool, _("  Tree conflicts: %u\n"), tree_conflicts));
-
-  if (skipped_paths > 0)
-    SVN_ERR(svn_cmdline_printf
-      (pool, _("  Skipped paths: %u\n"), skipped_paths));
+  struct notify_baton *nb = baton;
+
+  nb->text_conflicts = 0;
+  nb->prop_conflicts = 0;
+  nb->tree_conflicts = 0;
+  nb->skipped_paths = 0;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_cl__notifier_print_conflict_stats(void *baton, apr_pool_t *scratch_pool)
+{
+  struct notify_baton *nb = baton;
+
+  if (nb->text_conflicts > 0 || nb->prop_conflicts > 0
+      || nb->tree_conflicts > 0 || nb->skipped_paths > 0)
+    SVN_ERR(svn_cmdline_printf(scratch_pool,
+                               _("Summary of conflicts:\n")));
+
+  if (nb->text_conflicts > 0)
+    SVN_ERR(svn_cmdline_printf(scratch_pool,
+                               _("  Text conflicts: %d\n"),
+                               nb->text_conflicts));
+  if (nb->prop_conflicts > 0)
+    SVN_ERR(svn_cmdline_printf(scratch_pool,
+                               _("  Property conflicts: %d\n"),
+                               nb->prop_conflicts));
+  if (nb->tree_conflicts > 0)
+    SVN_ERR(svn_cmdline_printf(scratch_pool,
+                               _("  Tree conflicts: %d\n"),
+                               nb->tree_conflicts));
+  if (nb->skipped_paths > 0)
+    SVN_ERR(svn_cmdline_printf(scratch_pool,
+                               _("  Skipped paths: %d\n"),
+                               nb->skipped_paths));
 
   return SVN_NO_ERROR;
 }
@@ -997,7 +1002,8 @@ notify(void *baton, const svn_wc_notify_
 
     case svn_wc_notify_conflict_resolver_starting:
       /* Once all operations invoke the interactive conflict resolution after
-       * they've completed, we can run svn_cl__print_conflict_stats() here. */
+       * they've completed, we can run svn_cl__notifier_print_conflict_stats()
+       * here. */
       break;
 
     case svn_wc_notify_conflict_resolver_done:
@@ -1010,6 +1016,15 @@ notify(void *baton, const svn_wc_notify_
                                  n->url);
       if (err)
         goto print_error;
+      break;
+
+    case svn_wc_notify_move_broken:
+        err = svn_cmdline_printf(pool,
+                                 _("Breaking move with source path '%s'\n"),
+                                 path_local);
+      if (err)
+        goto print_error;
+      break;
 
     default:
       break;

Modified: subversion/branches/verify-keep-going/subversion/svn/patch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/patch-cmd.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/patch-cmd.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/patch-cmd.c Mon Mar 18 09:35:24 2013
@@ -92,7 +92,7 @@ svn_cl__patch(apr_getopt_t *os,
 
 
   if (! opt_state->quiet)
-    SVN_ERR(svn_cl__print_conflict_stats(ctx->notify_baton2, pool));
+    SVN_ERR(svn_cl__notifier_print_conflict_stats(ctx->notify_baton2, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/verify-keep-going/subversion/svn/propedit-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/propedit-cmd.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/propedit-cmd.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/propedit-cmd.c Mon Mar 18 09:35:24 2013
@@ -260,8 +260,8 @@ svn_cl__propedit(apr_getopt_t *os,
                 }
 
               /* Split the path if it is a file path. */
-              SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, abspath_or_url,
-                                       FALSE, subpool));
+              SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, abspath_or_url,
+                                        FALSE, FALSE, subpool));
 
               if (kind == svn_node_none)
                 return svn_error_createf(

Modified: subversion/branches/verify-keep-going/subversion/svn/proplist-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/proplist-cmd.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/proplist-cmd.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/proplist-cmd.c Mon Mar 18 09:35:24 2013
@@ -295,7 +295,7 @@ svn_cl__proplist(apr_getopt_t *os,
                                         opt_state->changelists,
                                         opt_state->show_inherited_props,
                                         pl_receiver, &pl_baton,
-                                        ctx, iterpool, iterpool),
+                                        ctx, iterpool),
                    errors, opt_state->quiet,
                    SVN_ERR_UNVERSIONED_RESOURCE,
                    SVN_ERR_ENTRY_NOT_FOUND,

Modified: subversion/branches/verify-keep-going/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/svn.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/svn.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/svn.c Mon Mar 18 09:35:24 2013
@@ -900,7 +900,8 @@ const svn_opt_subcommand_desc2_t svn_cl_
 "     source and target refer to the same branch, a previously committed\n"
 "     revision can be 'undone'. In a reverse range, N is greater than M in\n"
 "     '-r N:M', or the '-c' option is used with a negative number: '-c -M'\n"
-"     is equivalent to '-r M:<M-1>'.\n"
+"     is equivalent to '-r M:<M-1>'. Undoing changes like this is also known\n"
+"     as performing a 'reverse merge'.\n"
 "\n"
 "     Multiple '-c' and/or '-r' options may be specified and mixing of\n"
 "     forward and reverse ranges is allowed.\n"
@@ -1357,11 +1358,15 @@ const svn_opt_subcommand_desc2_t svn_cl_
     {opt_targets, 'R', opt_depth, 'q'} },
 
   { "revert", svn_cl__revert, {0}, N_
-    ("Restore pristine working copy file (undo most local edits).\n"
+    ("Restore pristine working copy state (undo local changes).\n"
      "usage: revert PATH...\n"
      "\n"
-     "  Note:  this subcommand does not require network access, and resolves\n"
-     "  any conflicted states.\n"),
+     "  Revert changes in the working copy at or within PATH, and remove\n"
+     "  conflict markers as well, if any.\n"
+     "\n"
+     "  This subcommand does not revert already committed changes.\n"
+     "  For information about undoing already committed changes, search\n"
+     "  the output of 'svn help merge' for 'undo'.\n"),
     {opt_targets, 'R', opt_depth, 'q', opt_changelist} },
 
   { "status", svn_cl__status, {"stat", "st"}, N_
@@ -1691,7 +1696,6 @@ sub_main(int argc, const char *argv[], a
   svn_boolean_t force_interactive = FALSE;
   svn_boolean_t use_notifier = TRUE;
   apr_hash_t *changelists;
-  const char *sqlite_exclusive;
   apr_hash_t *cfg_hash;
 
   received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
@@ -2123,7 +2127,7 @@ sub_main(int argc, const char *argv[], a
           {
             err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                    _("Changelist names must not be empty"));
-            return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+            return EXIT_ERROR(err);
           }
         apr_hash_set(changelists, opt_state.changelist,
                      APR_HASH_KEY_STRING, (void *)1);
@@ -2312,6 +2316,17 @@ sub_main(int argc, const char *argv[], a
                                      _("Unknown subcommand: '%s'\n"),
                                      first_arg_utf8));
               svn_cl__help(NULL, NULL, pool);
+
+              /* Be kind to people who try 'svn undo'. */
+              if (strcmp(first_arg_utf8, "undo") == 0)
+                {
+                  svn_error_clear
+                    (svn_cmdline_fprintf(stderr, pool,
+                                         _("Undo is done using either the "
+                                           "'svn revert' or the 'svn merge' "
+                                           "command.\n")));
+                }
+
               return EXIT_FAILURE;
             }
         }
@@ -2456,11 +2471,6 @@ sub_main(int argc, const char *argv[], a
         return EXIT_ERROR(err);
     }
 
-  /* Create a client context object. */
-  command_baton.opt_state = &opt_state;
-  SVN_INT_ERR(svn_client_create_context2(&ctx, cfg_hash, pool));
-  command_baton.ctx = ctx;
-
   /* Relocation is infinite-depth only. */
   if (opt_state.relocate)
     {
@@ -2519,27 +2529,49 @@ sub_main(int argc, const char *argv[], a
         }
     }
 
-  cfg_config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
+  cfg_config = apr_hash_get(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG,
                             APR_HASH_KEY_STRING);
 
   /* Update the options in the config */
   if (opt_state.config_options)
     {
       svn_error_clear(
-          svn_cmdline__apply_config_options(ctx->config,
+          svn_cmdline__apply_config_options(cfg_hash,
                                             opt_state.config_options,
                                             "svn: ", "--config-option"));
     }
 
-  svn_config_get(cfg_config, &sqlite_exclusive,
-                 SVN_CONFIG_SECTION_WORKING_COPY,
-                 SVN_CONFIG_OPTION_SQLITE_EXCLUSIVE,
-                 NULL);
-  if (!sqlite_exclusive)
-    svn_config_set(cfg_config,
+#if !defined(SVN_CL_NO_EXCLUSIVE_LOCK)
+  {
+    const char *exclusive_clients_option;
+    apr_array_header_t *exclusive_clients;
+
+    svn_config_get(cfg_config, &exclusive_clients_option,
                    SVN_CONFIG_SECTION_WORKING_COPY,
-                   SVN_CONFIG_OPTION_SQLITE_EXCLUSIVE,
-                   "true");
+                   SVN_CONFIG_OPTION_SQLITE_EXCLUSIVE_CLIENTS,
+                   NULL);
+    exclusive_clients = svn_cstring_split(exclusive_clients_option,
+                                          " ,", TRUE, pool);
+    for (i = 0; i < exclusive_clients->nelts; ++i)
+      {
+        const char *exclusive_client = APR_ARRAY_IDX(exclusive_clients, i,
+                                                     const char *);
+
+        /* This blocks other clients from accessing the wc.db so it must
+           be explicitly enabled.*/
+        if (!strcmp(exclusive_client, "svn"))
+          svn_config_set(cfg_config,
+                         SVN_CONFIG_SECTION_WORKING_COPY,
+                         SVN_CONFIG_OPTION_SQLITE_EXCLUSIVE,
+                         "true");
+      }
+  }
+#endif
+
+  /* Create a client context object. */
+  command_baton.opt_state = &opt_state;
+  SVN_INT_ERR(svn_client_create_context2(&ctx, cfg_hash, pool));
+  command_baton.ctx = ctx;
 
   /* If we're running a command that could result in a commit, verify
      that any log message we were given on the command line makes
@@ -2813,6 +2845,18 @@ sub_main(int argc, const char *argv[], a
                          "(type 'svn help cleanup' for details)"));
         }
 
+      if (err->apr_err == SVN_ERR_SQLITE_BUSY)
+        {
+          err = svn_error_quick_wrap(err,
+                                     _("Another process is blocking the "
+                                       "working copy database, or the "
+                                       "underlying filesystem does not "
+                                       "support file locking; if the working "
+                                       "copy is on a network filesystem, make "
+                                       "sure file locking has been enabled "
+                                       "on the file server"));
+        }
+
       return EXIT_ERROR(err);
     }
   else

Modified: subversion/branches/verify-keep-going/subversion/svn/switch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/switch-cmd.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/switch-cmd.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/switch-cmd.c Mon Mar 18 09:35:24 2013
@@ -193,13 +193,13 @@ svn_cl__switch(apr_getopt_t *os,
 
   if (! opt_state->quiet)
     {
-      err = svn_cl__print_conflict_stats(nwb.wrapped_baton, scratch_pool);
+      err = svn_cl__notifier_print_conflict_stats(nwb.wrapped_baton, scratch_pool);
       if (err)
         return svn_error_compose_create(externals_err, err);
     }
 
-  err = svn_cl__resolve_postponed_conflicts(ctx->conflict_baton2,
-                                            opt_state->depth,
+  err = svn_cl__resolve_postponed_conflicts(NULL,
+                                            ctx->conflict_baton2,
                                             opt_state->accept_which,
                                             opt_state->editor_cmd,
                                             ctx, scratch_pool);

Modified: subversion/branches/verify-keep-going/subversion/svn/update-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svn/update-cmd.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svn/update-cmd.c (original)
+++ subversion/branches/verify-keep-going/subversion/svn/update-cmd.c Mon Mar 18 09:35:24 2013
@@ -189,13 +189,14 @@ svn_cl__update(apr_getopt_t *os,
       /* ### Layering problem: This call assumes that the baton we're
        * passing is the one that was originally provided by
        * svn_cl__get_notifier(), but that isn't promised. */
-      err = svn_cl__print_conflict_stats(nwb.wrapped_baton, scratch_pool);
+      err = svn_cl__notifier_print_conflict_stats(nwb.wrapped_baton,
+                                                  scratch_pool);
       if (err)
         return svn_error_compose_create(externals_err, err);
     }
 
-  err = svn_cl__resolve_postponed_conflicts(ctx->conflict_baton2,
-                                            opt_state->depth,
+  err = svn_cl__resolve_postponed_conflicts(NULL,
+                                            ctx->conflict_baton2,
                                             opt_state->accept_which,
                                             opt_state->editor_cmd,
                                             ctx, scratch_pool);

Modified: subversion/branches/verify-keep-going/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svnadmin/svnadmin.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/verify-keep-going/subversion/svnadmin/svnadmin.c Mon Mar 18 09:35:24 2013
@@ -293,6 +293,8 @@ static const apr_getopt_option_t options
      N_("use repository format compatible with Subversion\n"
         "                             version ARG (\"1.5.5\", \"1.7\", etc.)")},
 
+    {"file", 'F', 1, N_("read repository paths from file ARG")},
+
     {NULL}
   };
 
@@ -340,9 +342,14 @@ static const svn_opt_subcommand_desc2_t 
   {'r', svnadmin__incremental, svnadmin__deltas, 'q', 'M'} },
 
   {"freeze", subcommand_freeze, {0}, N_
-   ("usage: svnadmin freeze REPOS_PATH PROGRAM [ARG...]\n\n"
-    "Run PROGRAM passing ARGS while holding a write-lock on REPOS_PATH.\n"),
-   {0} },
+   ("usage: 1. svnadmin freeze REPOS_PATH PROGRAM [ARG...]\n"
+    "               2. svnadmin freeze -F FILE PROGRAM [ARG...]\n\n"
+    "1. Run PROGRAM passing ARGS while holding a write-lock on REPOS_PATH.\n"
+    "\n"
+    "2. Like 1 except all repositories listed in FILE are locked. The file\n"
+    "   format is repository paths separated by newlines.  Repositories are\n"
+    "   locked in the same order as they are listed in the file.\n"),
+   {'F'} },
 
   {"help", subcommand_help, {"?", "h"}, N_
    ("usage: svnadmin help [SUBCOMMAND...]\n\n"
@@ -511,6 +518,7 @@ struct svnadmin_opt_state
                                                        --force-uuid */
   apr_uint64_t memory_cache_size;                   /* --memory-cache-size M */
   const char *parent_dir;
+  svn_stringbuf_t *filedata;                        /* --file */
 
   const char *config_dir;    /* Overriding Configuration Directory */
 };
@@ -1043,6 +1051,7 @@ static svn_error_t *
 subcommand_freeze(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 {
   struct svnadmin_opt_state *opt_state = baton;
+  apr_array_header_t *paths;
   apr_array_header_t *args;
   int i;
   struct freeze_baton_t b;
@@ -1053,13 +1062,25 @@ subcommand_freeze(apr_getopt_t *os, void
     return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0,
                             _("No program provided"));
 
+  if (!opt_state->filedata)
+    {
+      /* One repository on the command line. */
+      paths = apr_array_make(pool, 1, sizeof(const char *));
+      APR_ARRAY_PUSH(paths, const char *) = opt_state->repository_path;
+    }
+  else
+    {
+      /* All repositories in filedata. */
+      paths = svn_cstring_split(opt_state->filedata->data, "\n", FALSE, pool);
+    }
+
   b.command = APR_ARRAY_IDX(args, 0, const char *);
   b.args = apr_palloc(pool, sizeof(char *) * args->nelts + 1);
   for (i = 0; i < args->nelts; ++i)
     b.args[i] = APR_ARRAY_IDX(args, i, const char *);
   b.args[args->nelts] = NULL;
 
-  SVN_ERR(svn_repos_freeze(opt_state->repository_path, freeze_body, &b, pool));
+  SVN_ERR(svn_repos_freeze(paths, freeze_body, &b, pool));
 
   /* Make any non-zero status visible to the user. */
   if (b.status)
@@ -1919,6 +1940,7 @@ sub_main(int argc, const char *argv[], a
   int opt_id;
   apr_array_header_t *received_opts;
   int i;
+  svn_boolean_t dash_F_arg = FALSE;
 
   received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
 
@@ -1998,6 +2020,11 @@ sub_main(int argc, const char *argv[], a
         opt_state.memory_cache_size
             = 0x100000 * apr_strtoi64(opt_arg, NULL, 0);
         break;
+      case 'F':
+        SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+        SVN_INT_ERR(svn_stringbuf_from_file2(&(opt_state.filedata),
+                                             utf8_opt_arg, pool));
+        dash_F_arg = TRUE;
       case svnadmin__version:
         opt_state.version = TRUE;
         break;
@@ -2166,9 +2193,11 @@ sub_main(int argc, const char *argv[], a
         }
     }
 
-  /* Every subcommand except `help' requires a second argument -- the
-     repository path.  Parse it out here and store it in opt_state. */
-  if (subcommand->cmd_func != subcommand_help)
+  /* Every subcommand except `help' and `freeze' with '-F' require a
+     second argument -- the repository path.  Parse it out here and
+     store it in opt_state. */
+  if (!(subcommand->cmd_func == subcommand_help
+        || (subcommand->cmd_func == subcommand_freeze && dash_F_arg)))
     {
       const char *repos_path = NULL;
 

Modified: subversion/branches/verify-keep-going/subversion/svndumpfilter/svndumpfilter.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svndumpfilter/svndumpfilter.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svndumpfilter/svndumpfilter.c (original)
+++ subversion/branches/verify-keep-going/subversion/svndumpfilter/svndumpfilter.c Mon Mar 18 09:35:24 2013
@@ -210,6 +210,7 @@ struct parse_baton_t
   svn_boolean_t quiet;
   svn_boolean_t glob;
   svn_boolean_t drop_empty_revs;
+  svn_boolean_t drop_all_empty_revs;
   svn_boolean_t do_renumber_revs;
   svn_boolean_t preserve_revprops;
   svn_boolean_t skip_missing_merge_sources;
@@ -376,6 +377,7 @@ output_revision(struct revision_baton_t 
   int bytes_used;
   char buf[SVN_KEYLINE_MAXLEN];
   apr_hash_index_t *hi;
+  svn_boolean_t write_out_rev = FALSE;
   apr_pool_t *hash_pool = apr_hash_pool_get(rb->props);
   svn_stringbuf_t *props = svn_stringbuf_create_empty(hash_pool);
   apr_pool_t *subpool = svn_pool_create(hash_pool);
@@ -391,7 +393,8 @@ output_revision(struct revision_baton_t 
   if ((! rb->pb->preserve_revprops)
       && (! rb->has_nodes)
       && rb->had_dropped_nodes
-      && (! rb->pb->drop_empty_revs))
+      && (! rb->pb->drop_empty_revs)
+      && (! rb->pb->drop_all_empty_revs))
     {
       apr_hash_t *old_props = rb->props;
       rb->has_props = TRUE;
@@ -439,14 +442,21 @@ output_revision(struct revision_baton_t 
 
   /* write out the revision */
   /* Revision is written out in the following cases:
-     1. No --drop-empty-revs has been supplied.
+     1. If the revision has nodes or
+     it is revision 0 (Special case: To preserve the props on r0).
      2. --drop-empty-revs has been supplied,
-     but revision has not all nodes dropped
-     3. Revision had no nodes to begin with.
+     but revision has not all nodes dropped.
+     3. If no --drop-empty-revs or --drop-all-empty-revs have been supplied,
+     write out the revision which has no nodes to begin with.
   */
-  if (rb->has_nodes
-      || (! rb->pb->drop_empty_revs)
-      || (! rb->had_dropped_nodes))
+  if (rb->has_nodes || (rb->rev_orig == 0))
+    write_out_rev = TRUE;
+  else if (rb->pb->drop_empty_revs)
+    write_out_rev = ! rb->had_dropped_nodes;
+  else if (! rb->pb->drop_all_empty_revs)
+    write_out_rev = TRUE;
+
+  if (write_out_rev)
     {
       /* This revision is a keeper. */
       SVN_ERR(svn_stream_write(rb->pb->out_stream,
@@ -994,6 +1004,7 @@ static svn_opt_subcommand_t
 enum
   {
     svndumpfilter__drop_empty_revs = SVN_OPT_FIRST_LONGOPT_ID,
+    svndumpfilter__drop_all_empty_revs,
     svndumpfilter__renumber_revs,
     svndumpfilter__preserve_revprops,
     svndumpfilter__skip_missing_merge_sources,
@@ -1023,6 +1034,9 @@ static const apr_getopt_option_t options
      N_("Treat the path prefixes as file glob patterns.") },
     {"drop-empty-revs",    svndumpfilter__drop_empty_revs, 0,
      N_("Remove revisions emptied by filtering.")},
+    {"drop-all-empty-revs",    svndumpfilter__drop_all_empty_revs, 0,
+     N_("Remove all empty revisions found in dumpstream\n"
+        "                             except revision 0.")},
     {"renumber-revs",      svndumpfilter__renumber_revs, 0,
      N_("Renumber revisions left after filtering.") },
     {"skip-missing-merge-sources",
@@ -1045,7 +1059,8 @@ static const svn_opt_subcommand_desc2_t 
     {"exclude", subcommand_exclude, {0},
      N_("Filter out nodes with given prefixes from dumpstream.\n"
         "usage: svndumpfilter exclude PATH_PREFIX...\n"),
-     {svndumpfilter__drop_empty_revs, svndumpfilter__renumber_revs,
+     {svndumpfilter__drop_empty_revs, svndumpfilter__drop_all_empty_revs,
+      svndumpfilter__renumber_revs,
       svndumpfilter__skip_missing_merge_sources, svndumpfilter__targets,
       svndumpfilter__preserve_revprops, svndumpfilter__quiet,
       svndumpfilter__glob} },
@@ -1053,7 +1068,8 @@ static const svn_opt_subcommand_desc2_t 
     {"include", subcommand_include, {0},
      N_("Filter out nodes without given prefixes from dumpstream.\n"
         "usage: svndumpfilter include PATH_PREFIX...\n"),
-     {svndumpfilter__drop_empty_revs, svndumpfilter__renumber_revs,
+     {svndumpfilter__drop_empty_revs, svndumpfilter__drop_all_empty_revs,
+      svndumpfilter__renumber_revs,
       svndumpfilter__skip_missing_merge_sources, svndumpfilter__targets,
       svndumpfilter__preserve_revprops, svndumpfilter__quiet,
       svndumpfilter__glob} },
@@ -1076,6 +1092,7 @@ struct svndumpfilter_opt_state
   svn_boolean_t glob;                    /* --pattern           */
   svn_boolean_t version;                 /* --version           */
   svn_boolean_t drop_empty_revs;         /* --drop-empty-revs   */
+  svn_boolean_t drop_all_empty_revs;     /* --drop-all-empty-revs */
   svn_boolean_t help;                    /* --help or -?        */
   svn_boolean_t renumber_revs;           /* --renumber-revs     */
   svn_boolean_t preserve_revprops;       /* --preserve-revprops */
@@ -1107,9 +1124,11 @@ parse_baton_initialize(struct parse_bato
   /* Ignore --renumber-revs if there can't possibly be
      anything to renumber. */
   baton->do_renumber_revs =
-    (opt_state->renumber_revs && opt_state->drop_empty_revs);
+    (opt_state->renumber_revs && (opt_state->drop_empty_revs
+                                  || opt_state->drop_all_empty_revs));
 
   baton->drop_empty_revs = opt_state->drop_empty_revs;
+  baton->drop_all_empty_revs = opt_state->drop_all_empty_revs;
   baton->preserve_revprops = opt_state->preserve_revprops;
   baton->quiet = opt_state->quiet;
   baton->glob = opt_state->glob;
@@ -1188,11 +1207,13 @@ do_filter(apr_getopt_t *os,
         {
           SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
                                       do_exclude
-                                      ? opt_state->drop_empty_revs
+                                      ? (opt_state->drop_empty_revs
+                                         || opt_state->drop_all_empty_revs)
                                         ? _("Excluding (and dropping empty "
                                             "revisions for) prefix patterns:\n")
                                         : _("Excluding prefix patterns:\n")
-                                      : opt_state->drop_empty_revs
+                                      : (opt_state->drop_empty_revs
+                                         || opt_state->drop_all_empty_revs)
                                         ? _("Including (and dropping empty "
                                             "revisions for) prefix patterns:\n")
                                         : _("Including prefix patterns:\n")));
@@ -1201,11 +1222,13 @@ do_filter(apr_getopt_t *os,
         {
           SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
                                       do_exclude
-                                      ? opt_state->drop_empty_revs
+                                      ? (opt_state->drop_empty_revs
+                                         || opt_state->drop_all_empty_revs)
                                         ? _("Excluding (and dropping empty "
                                             "revisions for) prefixes:\n")
                                         : _("Excluding prefixes:\n")
-                                      : opt_state->drop_empty_revs
+                                      : (opt_state->drop_empty_revs
+                                         || opt_state->drop_all_empty_revs)
                                         ? _("Including (and dropping empty "
                                             "revisions for) prefixes:\n")
                                         : _("Including prefixes:\n")));
@@ -1427,6 +1450,9 @@ main(int argc, const char *argv[])
         case svndumpfilter__drop_empty_revs:
           opt_state.drop_empty_revs = TRUE;
           break;
+        case svndumpfilter__drop_all_empty_revs:
+          opt_state.drop_all_empty_revs = TRUE;
+          break;
         case svndumpfilter__renumber_revs:
           opt_state.renumber_revs = TRUE;
           break;
@@ -1448,6 +1474,16 @@ main(int argc, const char *argv[])
         }  /* close `switch' */
     }  /* close `while' */
 
+  /* Disallow simultaneous use of both --drop-empty-revs and
+     --drop-all-empty-revs. */
+  if (opt_state.drop_empty_revs && opt_state.drop_all_empty_revs)
+    {
+      err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+                             _("--drop-empty-revs cannot be used with "
+                               "--drop-all-empty-revs"));
+      return svn_cmdline_handle_exit_error(err, pool, "svndumpfilter: ");
+    }
+
   /* If the user asked for help, then the rest of the arguments are
      the names of subcommands to get help on (if any), or else they're
      just typos/mistakes.  Whatever the case, the subcommand to

Modified: subversion/branches/verify-keep-going/subversion/svnmucc/svnmucc.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svnmucc/svnmucc.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svnmucc/svnmucc.c (original)
+++ subversion/branches/verify-keep-going/subversion/svnmucc/svnmucc.c Mon Mar 18 09:35:24 2013
@@ -682,23 +682,20 @@ fetch_props_func(apr_hash_t **props,
 }
 
 static svn_error_t *
-fetch_kind_func(svn_kind_t *kind,
+fetch_kind_func(svn_node_kind_t *kind,
                 void *baton,
                 const char *path,
                 svn_revnum_t base_revision,
                 apr_pool_t *scratch_pool)
 {
   struct fetch_baton *fb = baton;
-  svn_node_kind_t node_kind;
 
   if (! SVN_IS_VALID_REVNUM(base_revision))
     base_revision = fb->head;
 
-  SVN_ERR(svn_ra_check_path(fb->session, path, base_revision, &node_kind,
+  SVN_ERR(svn_ra_check_path(fb->session, path, base_revision, kind,
                              scratch_pool));
 
-  *kind = svn__kind_from_node_kind(node_kind, FALSE);
-
   return SVN_NO_ERROR;
 }
 
@@ -1410,6 +1407,9 @@ main(int argc, const char **argv)
                      no_auth_cache, base_revision, pool)))
     handle_error(err, pool);
 
+  /* Ensure that stdout is flushed, so the user will see all results. */
+  svn_error_clear(svn_cmdline_fflush(stdout));
+
   svn_pool_destroy(pool);
   return EXIT_SUCCESS;
 }

Modified: subversion/branches/verify-keep-going/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svnrdump/dump_editor.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/verify-keep-going/subversion/svnrdump/dump_editor.c Mon Mar 18 09:35:24 2013
@@ -1194,14 +1194,13 @@ fetch_props_func(apr_hash_t **props,
 }
 
 static svn_error_t *
-fetch_kind_func(svn_kind_t *kind,
+fetch_kind_func(svn_node_kind_t *kind,
                 void *baton,
                 const char *path,
                 svn_revnum_t base_revision,
                 apr_pool_t *scratch_pool)
 {
   struct dump_edit_baton *eb = baton;
-  svn_node_kind_t node_kind;
 
   if (path[0] == '/')
     path += 1;
@@ -1209,10 +1208,9 @@ fetch_kind_func(svn_kind_t *kind,
   if (! SVN_IS_VALID_REVNUM(base_revision))
     base_revision = eb->current_revision - 1;
 
-  SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
+  SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, kind,
                             scratch_pool));
 
-  *kind = svn__kind_from_node_kind(node_kind, FALSE);
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/verify-keep-going/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/svnrdump/load_editor.c?rev=1457684&r1=1457683&r2=1457684&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/verify-keep-going/subversion/svnrdump/load_editor.c Mon Mar 18 09:35:24 2013
@@ -465,22 +465,20 @@ fetch_props_func(apr_hash_t **props,
 }
 
 static svn_error_t *
-fetch_kind_func(svn_kind_t *kind,
+fetch_kind_func(svn_node_kind_t *kind,
                 void *baton,
                 const char *path,
                 svn_revnum_t base_revision,
                 apr_pool_t *scratch_pool)
 {
   struct revision_baton *rb = baton;
-  svn_node_kind_t node_kind;
 
   if (! SVN_IS_VALID_REVNUM(base_revision))
     base_revision = rb->rev - 1;
 
   SVN_ERR(svn_ra_check_path(rb->pb->aux_session, path, base_revision,
-                            &node_kind, scratch_pool));
+                            kind, scratch_pool));
 
-  *kind = svn__kind_from_node_kind(node_kind, FALSE);
   return SVN_NO_ERROR;
 }