You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/10/21 04:00:47 UTC

svn commit: r1400556 [23/29] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/ contrib/client-side/emacs/ contrib/client-side/svn-push/ contrib/client-side/svnmerge/ contrib/hook-...

Modified: subversion/branches/ev2-export/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/cl.h?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/cl.h (original)
+++ subversion/branches/ev2-export/subversion/svn/cl.h Sun Oct 21 02:00:31 2012
@@ -203,7 +203,6 @@ typedef struct svn_cl__opt_state_t
   const char *merge_cmd;         /* the external merge command to use */
   const char *editor_cmd;        /* the external editor command to use */
   svn_boolean_t record_only;     /* whether to record mergeinfo */
-  svn_boolean_t symmetric_merge; /* symmetric merge */
   const char *old_target;        /* diff target */
   const char *new_target;        /* diff target */
   svn_boolean_t relocate;        /* rewrite urls (svn switch) */
@@ -237,11 +236,8 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t show_diff;        /* produce diff output (maps to --diff) */
   svn_boolean_t allow_mixed_rev; /* Allow operation on mixed-revision WC */
   svn_boolean_t include_externals; /* Recurses (in)to file & dir externals */
-  const char *search_pattern;     /* pattern argument for --search */
-  svn_boolean_t case_insensitive_search; /* perform case-insensitive search */
-
-  svn_wc_conflict_resolver_func2_t conflict_func;
-  void *conflict_baton;
+  svn_boolean_t show_inherited_props; /* get inherited properties */
+  apr_array_header_t* search_patterns; /* pattern arguments for --search */
 } svn_cl__opt_state_t;
 
 
@@ -334,37 +330,58 @@ svn_cl__check_cancel(void *baton);
 
 /* Various conflict-resolution callbacks. */
 
-typedef struct svn_cl__conflict_baton_t {
-  svn_cl__accept_t accept_which;
-  apr_hash_t *config;
-  const char *editor_cmd;
-  svn_boolean_t external_failed;
-  svn_cmdline_prompt_baton_t *pb;
-  const char *path_prefix;
-} svn_cl__conflict_baton_t;
-
-/* Create and return a conflict baton in *B, allocated from POOL, with the
- * values ACCEPT_WHICH, CONFIG, EDITOR_CMD and PB placed in the same-named
- * fields of the baton, and its 'external_failed' field initialised to FALSE. */
-svn_error_t *
-svn_cl__conflict_baton_make(svn_cl__conflict_baton_t **b,
-                            svn_cl__accept_t accept_which,
-                            apr_hash_t *config,
-                            const char *editor_cmd,
-                            svn_cmdline_prompt_baton_t *pb,
-                            apr_pool_t *pool);
+/* Opaque baton type for svn_cl__conflict_func_interactive(). */
+typedef struct svn_cl__interactive_conflict_baton_t
+  svn_cl__interactive_conflict_baton_t;
+
+/* Create and return an baton for use with svn_cl__conflict_func_interactive
+ * in *B, allocated from RESULT_POOL, and initialised with the values
+ * ACCEPT_WHICH, CONFIG, EDITOR_CMD, CANCEL_FUNC and CANCEL_BATON. */
+svn_error_t *
+svn_cl__get_conflict_func_interactive_baton(
+  svn_cl__interactive_conflict_baton_t **b,
+  svn_cl__accept_t accept_which,
+  apr_hash_t *config,
+  const char *editor_cmd,
+  svn_cancel_func_t cancel_func,
+  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. */
 svn_error_t *
-svn_cl__conflict_handler(svn_wc_conflict_result_t **result,
-                         const svn_wc_conflict_description2_t *desc,
-                         void *baton,
-                         apr_pool_t *result_pool,
-                         apr_pool_t *scratch_pool);
-
+svn_cl__conflict_func_interactive(svn_wc_conflict_result_t **result,
+                                  const svn_wc_conflict_description2_t *desc,
+                                  void *baton,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool);
+
+/* Create an return a baton for use with svn_cl__conflict_func_postpone(),
+ * allocated in RESULT_POOL. */
+void *
+svn_cl__get_conflict_func_postpone_baton(apr_pool_t *result_pool);
+
+/* A conflict-resolution callback which postpones all conflicts and
+ * remembers conflicted paths in BATON. */
+svn_error_t *
+svn_cl__conflict_func_postpone(svn_wc_conflict_result_t **result,
+                               const svn_wc_conflict_description2_t *desc,
+                               void *baton,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool);
+
+/* Run the interactive conflict resolver, obtained internally from
+ * svn_cl__get_conflict_func_interactive(), on any conflicted paths
+ * stored in the BATON obtained from svn_cl__get_conflict_func_postpone(). */
+svn_error_t *
+svn_cl__resolve_postponed_conflicts(void *baton,
+                                    svn_depth_t depth,
+                                    svn_cl__accept_t accept_which,
+                                    const char *editor_cmd,
+                                    svn_client_ctx_t *ctx,
+                                    apr_pool_t *scratch_pool);
 
 
 /*** Command-line output functions -- printing to the user. ***/
@@ -461,12 +478,15 @@ svn_cl__print_prop_hash(svn_stream_t *ou
                         svn_boolean_t names_only,
                         apr_pool_t *pool);
 
-/* Same as svn_cl__print_prop_hash(), only output xml to *OUTSTR.  If *OUTSTR is
-   NULL, allocate it first from POOL, otherwise append to it. */
+/* Similar to svn_cl__print_prop_hash(), only output xml to *OUTSTR.
+   If INHERITED_PROPS is true, then PROP_HASH contains inherited properties,
+   otherwise PROP_HASH contains explicit properties.  If *OUTSTR is NULL,
+   allocate it first from POOL, otherwise append to it. */
 svn_error_t *
 svn_cl__print_xml_prop_hash(svn_stringbuf_t **outstr,
                             apr_hash_t *prop_hash,
                             svn_boolean_t names_only,
+                            svn_boolean_t inherited_props,
                             apr_pool_t *pool);
 
 /* Output a commit xml element to *OUTSTR.  If *OUTSTR is NULL, allocate it
@@ -584,6 +604,7 @@ svn_cl__merge_file(const char *base_path
                    const char *my_path,
                    const char *merged_path,
                    const char *wc_path,
+                   const char *path_prefix,
                    const char *editor_cmd,
                    apr_hash_t *config,
                    svn_boolean_t *remains_in_conflict,
@@ -618,14 +639,6 @@ svn_cl__notifier_mark_export(void *baton
 svn_error_t *
 svn_cl__notifier_mark_wc_to_repos_copy(void *baton);
 
-/* Return TRUE if any conflicts were detected during notification. */
-svn_boolean_t
-svn_cl__notifier_check_conflicts(void *baton);
-
-/* Return a sorted array of conflicted paths detected during notification. */
-apr_array_header_t *
-svn_cl__notifier_get_conflicted_paths(void *baton, apr_pool_t *result_pool);
-
 /* Baton for use with svn_cl__check_externals_failed_notify_wrapper(). */
 struct svn_cl__check_externals_failed_notify_baton
 {
@@ -873,15 +886,6 @@ svn_cl__check_related_source_and_target(
                                         svn_client_ctx_t *ctx,
                                         apr_pool_t *pool);
 
-/* Run the conflict resolver for all targets in the TARGETS list with
- * the specified DEPTH. */
-svn_error_t *
-svn_cl__resolve_conflicts(apr_array_header_t *targets,
-                          svn_depth_t depth,
-                          const svn_cl__opt_state_t *opt_state,
-                          svn_client_ctx_t *ctx,
-                          apr_pool_t *scratch_pool);
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/ev2-export/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/conflict-callbacks.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/ev2-export/subversion/svn/conflict-callbacks.c Sun Oct 21 02:00:31 2012
@@ -33,6 +33,7 @@
 #include "svn_dirent_uri.h"
 #include "svn_types.h"
 #include "svn_pools.h"
+#include "svn_sorts.h"
 
 #include "cl.h"
 #include "tree-conflicts.h"
@@ -41,22 +42,37 @@
 
 
 
+struct svn_cl__interactive_conflict_baton_t {
+  svn_cl__accept_t accept_which;
+  apr_hash_t *config;
+  const char *editor_cmd;
+  svn_boolean_t external_failed;
+  svn_cmdline_prompt_baton_t *pb;
+  const char *path_prefix;
+};
 
 svn_error_t *
-svn_cl__conflict_baton_make(svn_cl__conflict_baton_t **b,
-                            svn_cl__accept_t accept_which,
-                            apr_hash_t *config,
-                            const char *editor_cmd,
-                            svn_cmdline_prompt_baton_t *pb,
-                            apr_pool_t *pool)
+svn_cl__get_conflict_func_interactive_baton(
+  svn_cl__interactive_conflict_baton_t **b,
+  svn_cl__accept_t accept_which,
+  apr_hash_t *config,
+  const char *editor_cmd,
+  svn_cancel_func_t cancel_func,
+  void *cancel_baton,
+  apr_pool_t *result_pool)
 {
-  *b = apr_palloc(pool, sizeof(**b));
+  svn_cmdline_prompt_baton_t *pb = apr_palloc(result_pool, sizeof(*pb));
+  pb->cancel_func = cancel_func;
+  pb->cancel_baton = cancel_baton;
+
+  *b = apr_palloc(result_pool, sizeof(**b));
   (*b)->accept_which = accept_which;
   (*b)->config = config;
   (*b)->editor_cmd = editor_cmd;
   (*b)->external_failed = FALSE;
   (*b)->pb = pb;
-  SVN_ERR(svn_dirent_get_absolute(&(*b)->path_prefix, "", pool));
+  SVN_ERR(svn_dirent_get_absolute(&(*b)->path_prefix, "", result_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -180,7 +196,7 @@ show_conflicts(const svn_wc_conflict_des
 static svn_error_t *
 open_editor(svn_boolean_t *performed_edit,
             const svn_wc_conflict_description2_t *desc,
-            svn_cl__conflict_baton_t *b,
+            svn_cl__interactive_conflict_baton_t *b,
             apr_pool_t *pool)
 {
   svn_error_t *err;
@@ -232,7 +248,7 @@ open_editor(svn_boolean_t *performed_edi
 static svn_error_t *
 launch_resolver(svn_boolean_t *performed_edit,
                 const svn_wc_conflict_description2_t *desc,
-                svn_cl__conflict_baton_t *b,
+                svn_cl__interactive_conflict_baton_t *b,
                 apr_pool_t *pool)
 {
   svn_error_t *err;
@@ -265,17 +281,359 @@ launch_resolver(svn_boolean_t *performed
   return SVN_NO_ERROR;
 }
 
+/* Ask the user what to do about the text conflict described by DESC.
+ * Return the answer in RESULT. B is the conflict baton for this
+ * conflict resolution session.
+ * SCRATCH_POOL is used for temporary allocations. */
+static svn_error_t *
+handle_text_conflict(svn_wc_conflict_result_t *result,
+                     const svn_wc_conflict_description2_t *desc,
+                     svn_cl__interactive_conflict_baton_t *b,
+                     apr_pool_t *scratch_pool)
+{
+  const char *answer;
+  char *prompt;
+  svn_boolean_t diff_allowed = FALSE;
+  /* Have they done something that might have affected the merged
+     file (so that we need to save a .edited copy)? */
+  svn_boolean_t performed_edit = FALSE;
+  /* Have they done *something* (edit, look at diff, etc) to
+     give them a rational basis for choosing (r)esolved? */
+  svn_boolean_t knows_something = FALSE;
+
+  SVN_ERR_ASSERT(desc->kind == svn_wc_conflict_kind_text);
+
+  SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                              _("Conflict discovered in file '%s'.\n"),
+                              svn_cl__local_style_skip_ancestor(
+                                b->path_prefix, desc->local_abspath,
+                                scratch_pool)));
+
+  /* Diffing can happen between base and merged, to show conflict
+     markers to the user (this is the typical 3-way merge
+     scenario), or if no base is available, we can show a diff
+     between mine and theirs. */
+  if ((desc->merged_file && desc->base_abspath)
+      || (!desc->base_abspath && desc->my_abspath && desc->their_abspath))
+    diff_allowed = TRUE;
+
+  while (TRUE)
+    {
+      svn_pool_clear(scratch_pool);
+
+      prompt = apr_pstrdup(scratch_pool, _("Select: (p) postpone"));
+
+      if (diff_allowed)
+        {
+          prompt = apr_pstrcat(scratch_pool, prompt,
+                               _(", (df) diff-full, (e) edit, (m) merge"),
+                               (char *)NULL);
+
+          if (knows_something)
+            prompt = apr_pstrcat(scratch_pool, prompt, _(", (r) resolved"),
+                                 (char *)NULL);
+
+          if (! desc->is_binary)
+            prompt = apr_pstrcat(scratch_pool, prompt,
+                                 _(",\n        (mc) mine-conflict, "
+                                   "(tc) theirs-conflict"),
+                                 (char *)NULL);
+        }
+      else
+        {
+          if (knows_something)
+            prompt = apr_pstrcat(scratch_pool, prompt, _(", (r) resolved"),
+                                 (char *)NULL);
+          prompt = apr_pstrcat(scratch_pool, prompt,
+                               _(",\n        "
+                                 "(mf) mine-full, (tf) theirs-full"),
+                               (char *)NULL);
+        }
+
+      prompt = apr_pstrcat(scratch_pool, prompt, ",\n        ", (char *)NULL);
+      prompt = apr_pstrcat(scratch_pool, prompt,
+                           _("(s) show all options: "),
+                           (char *)NULL);
+
+      SVN_ERR(svn_cmdline_prompt_user2(&answer, prompt, b->pb, scratch_pool));
+
+      if (strcmp(answer, "s") == 0)
+        {
+          /* These are used in svn_cl__accept_from_word(). */
+          SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+          _("\n"
+            "  (e)  edit             - change merged file in an editor\n"
+            "  (df) diff-full        - show all changes made to merged "
+                                      "file\n"
+            "  (r)  resolved         - accept merged version of file\n"
+            "\n"
+            "  (dc) display-conflict - show all conflicts "
+                                      "(ignoring merged version)\n"
+            "  (mc) mine-conflict    - accept my version for all "
+                                      "conflicts (same)\n"
+            "  (tc) theirs-conflict  - accept their version for all "
+                                      "conflicts (same)\n"
+            "\n"
+            "  (mf) mine-full        - accept my version of entire file "
+                                      "(even non-conflicts)\n"
+            "  (tf) theirs-full      - accept their version of entire "
+                                      "file (same)\n"
+            "\n"
+            "  (p)  postpone         - mark the conflict to be "
+                                      "resolved later\n"
+            "  (m)  merge            - use internal merge tool to "
+                                      "resolve conflict\n"
+            "  (l)  launch           - launch external tool to "
+                                      "resolve conflict\n"
+            "  (s)  show all         - show this list\n\n")));
+        }
+      else if (strcmp(answer, "p") == 0 || strcmp(answer, ":-P") == 0)
+        {
+          /* Do nothing, let file be marked conflicted. */
+          result->choice = svn_wc_conflict_choose_postpone;
+          break;
+        }
+      else if (strcmp(answer, "mc") == 0 || strcmp(answer, "X-)") == 0)
+        {
+          if (desc->is_binary)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                          _("Invalid option; cannot choose "
+                                            "based on conflicts in a "
+                                            "binary file.\n\n")));
+              continue;
+            }
+          result->choice = svn_wc_conflict_choose_mine_conflict;
+          if (performed_edit)
+            result->save_merged = TRUE;
+          break;
+        }
+      else if (strcmp(answer, "tc") == 0 || strcmp(answer, "X-(") == 0)
+        {
+          if (desc->is_binary)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                          _("Invalid option; cannot choose "
+                                            "based on conflicts in a "
+                                            "binary file.\n\n")));
+              continue;
+            }
+          result->choice = svn_wc_conflict_choose_theirs_conflict;
+          if (performed_edit)
+            result->save_merged = TRUE;
+          break;
+        }
+      else if (strcmp(answer, "mf") == 0 || strcmp(answer, ":-)") == 0)
+        {
+          result->choice = svn_wc_conflict_choose_mine_full;
+          if (performed_edit)
+            result->save_merged = TRUE;
+          break;
+        }
+      else if (strcmp(answer, "tf") == 0 || strcmp(answer, ":-(") == 0)
+        {
+          result->choice = svn_wc_conflict_choose_theirs_full;
+          if (performed_edit)
+            result->save_merged = TRUE;
+          break;
+        }
+      else if (strcmp(answer, "dc") == 0)
+        {
+          if (desc->is_binary)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                          _("Invalid option; cannot "
+                                            "display conflicts for a "
+                                            "binary file.\n\n")));
+              continue;
+            }
+          else if (! (desc->my_abspath && desc->base_abspath &&
+                      desc->their_abspath))
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                          _("Invalid option; original "
+                                            "files not available.\n\n")));
+              continue;
+            }
+          SVN_ERR(show_conflicts(desc, scratch_pool));
+          knows_something = TRUE;
+        }
+      else if (strcmp(answer, "df") == 0)
+        {
+          if (! diff_allowed)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                             _("Invalid option; there's no "
+                                "merged version to diff.\n\n")));
+              continue;
+            }
+
+          SVN_ERR(show_diff(desc, scratch_pool));
+          knows_something = TRUE;
+        }
+      else if (strcmp(answer, "e") == 0 || strcmp(answer, ":-E") == 0)
+        {
+          SVN_ERR(open_editor(&performed_edit, desc, b, scratch_pool));
+          if (performed_edit)
+            knows_something = TRUE;
+        }
+      else if (strcmp(answer, "m") == 0 || strcmp(answer, ":-g") == 0 ||
+               strcmp(answer, "=>-") == 0 || strcmp(answer, ":>.") == 0)
+        {
+          if (desc->kind != svn_wc_conflict_kind_text)
+            {
+              SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                          _("Invalid option; can only "
+                                            "resolve text conflicts with "
+                                            "the internal merge tool."
+                                            "\n\n")));
+              continue;
+            }
+
+          if (desc->base_abspath && desc->their_abspath &&
+              desc->my_abspath && desc->merged_file)
+            {
+              svn_boolean_t remains_in_conflict;
+
+              SVN_ERR(svn_cl__merge_file(desc->base_abspath,
+                                         desc->their_abspath,
+                                         desc->my_abspath,
+                                         desc->merged_file,
+                                         desc->local_abspath,
+                                         b->path_prefix,
+                                         b->editor_cmd,
+                                         b->config,
+                                         &remains_in_conflict,
+                                         scratch_pool));
+              knows_something = !remains_in_conflict;
+            }
+          else
+            SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                        _("Invalid option.\n\n")));
+        }
+      else if (strcmp(answer, "l") == 0 || strcmp(answer, ":-l") == 0)
+        {
+          if (desc->base_abspath && desc->their_abspath &&
+              desc->my_abspath && desc->merged_file)
+            {
+              SVN_ERR(launch_resolver(&performed_edit, desc, b, scratch_pool));
+              if (performed_edit)
+                knows_something = TRUE;
+            }
+          else
+            SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                        _("Invalid option.\n\n")));
+        }
+      else if (strcmp(answer, "r") == 0)
+        {
+          /* We only allow the user accept the merged version of
+             the file if they've edited it, or at least looked at
+             the diff. */
+          if (knows_something)
+            {
+              result->choice = svn_wc_conflict_choose_merged;
+              break;
+            }
+          else
+            SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                        _("Invalid option.\n\n")));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Ask the user what to do about the property conflict described by DESC.
+ * Return the answer in RESULT. B is the conflict baton for this
+ * conflict resolution session.
+ * SCRATCH_POOL is used for temporary allocations. */
+static svn_error_t *
+handle_prop_conflict(svn_wc_conflict_result_t *result,
+                     const svn_wc_conflict_description2_t *desc,
+                     svn_cl__interactive_conflict_baton_t *b,
+                     apr_pool_t *scratch_pool)
+{
+  const char *answer;
+  const char *prompt;
+  svn_stringbuf_t *prop_reject;
+  apr_pool_t *iterpool;
+
+  SVN_ERR_ASSERT(desc->kind == svn_wc_conflict_kind_property);
+
+  SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                              _("Conflict for property '%s' discovered"
+                                " on '%s'.\n"),
+                              desc->property_name,
+                              svn_cl__local_style_skip_ancestor(
+                                b->path_prefix, desc->local_abspath,
+                                scratch_pool)));
+
+  /* ### Currently, the only useful information in a prop conflict
+   * ### description is the .prej file path, which, possibly due to
+   * ### deceitful interference from outer space, is stored in the
+   * ### 'their_abspath' field of the description.
+   * ### This needs to be fixed so we can present better options here. */
+  if (desc->their_abspath)
+    {
+      /* ### The library dumps an svn_string_t into a temp file, and
+       * ### we read it back from the file into an svn_stringbuf_t here.
+       * ### That's rather silly. We should be passed svn_string_t's
+       * ### containing the old/mine/theirs values instead. */
+      SVN_ERR(svn_stringbuf_from_file2(&prop_reject,
+                                       desc->their_abspath,
+                                       scratch_pool));
+      /* Print reject file contents. */
+      SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+                                  "%s\n", prop_reject->data));
+    }
+  else
+    {
+      /* Nothing much we can do without a prej file... */
+      result->choice = svn_wc_conflict_choose_postpone;
+      return SVN_NO_ERROR;
+    }
+
+  iterpool = svn_pool_create(scratch_pool);
+  while (TRUE)
+    {
+      svn_pool_clear(iterpool);
+
+      prompt = _("Select: (p) postpone, (mf) mine-full, (tf) theirs-full: ");
+
+      SVN_ERR(svn_cmdline_prompt_user2(&answer, prompt, b->pb, iterpool));
+
+      if (strcmp(answer, "p") == 0 || strcmp(answer, ":-P") == 0)
+        {
+          /* Do nothing, let property be marked conflicted. */
+          result->choice = svn_wc_conflict_choose_postpone;
+          break;
+        }
+      else if (strcmp(answer, "mf") == 0 || strcmp(answer, ":-)") == 0)
+        {
+          result->choice = svn_wc_conflict_choose_mine_full;
+          break;
+        }
+      else if (strcmp(answer, "tf") == 0 || strcmp(answer, ":-(") == 0)
+        {
+          result->choice = svn_wc_conflict_choose_theirs_full;
+          break;
+        }
+    }
+  svn_pool_destroy(iterpool);
+
+  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_handler(svn_wc_conflict_result_t **result,
-                         const svn_wc_conflict_description2_t *desc,
-                         void *baton,
-                         apr_pool_t *result_pool,
-                         apr_pool_t *scratch_pool)
+svn_cl__conflict_func_interactive(svn_wc_conflict_result_t **result,
+                                  const svn_wc_conflict_description2_t *desc,
+                                  void *baton,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
 {
-  svn_cl__conflict_baton_t *b = baton;
+  svn_cl__interactive_conflict_baton_t *b = baton;
   svn_error_t *err;
   apr_pool_t *subpool;
 
@@ -409,332 +767,11 @@ svn_cl__conflict_handler(svn_wc_conflict
   */
   if (((desc->node_kind == svn_node_file)
        && (desc->action == svn_wc_conflict_action_edit)
-       && (desc->reason == svn_wc_conflict_reason_edited))
-      || (desc->kind == svn_wc_conflict_kind_property))
-  {
-      const char *answer;
-      char *prompt;
-      svn_boolean_t diff_allowed = FALSE;
-      /* Have they done something that might have affected the merged
-         file (so that we need to save a .edited copy)? */
-      svn_boolean_t performed_edit = FALSE;
-      /* Have they done *something* (edit, look at diff, etc) to
-         give them a rational basis for choosing (r)esolved? */
-      svn_boolean_t knows_something = FALSE;
-
-      if (desc->kind == svn_wc_conflict_kind_text)
-        SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                    _("Conflict discovered in file '%s'.\n"),
-                                    svn_cl__local_style_skip_ancestor(
-                                      b->path_prefix, desc->local_abspath,
-                                      subpool)));
-      else if (desc->kind == svn_wc_conflict_kind_property)
-        {
-          SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                      _("Conflict for property '%s' discovered"
-                                        " on '%s'.\n"),
-                                      desc->property_name,
-                                      svn_cl__local_style_skip_ancestor(
-                                        b->path_prefix, desc->local_abspath,
-                                        subpool)));
-
-          if ((!desc->my_abspath && desc->their_abspath)
-              || (desc->my_abspath && !desc->their_abspath))
-            {
-              /* One agent wants to change the property, one wants to
-                 delete it.  This is not something we can diff, so we
-                 just tell the user. */
-              svn_stringbuf_t *myval = NULL, *theirval = NULL;
-
-              if (desc->my_abspath)
-                {
-                  SVN_ERR(svn_stringbuf_from_file2(&myval, desc->my_abspath,
-                                                   subpool));
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                        _("They want to delete the property, "
-                          "you want to change the value to '%s'.\n"),
-                          myval->data));
-                }
-              else
-                {
-                  SVN_ERR(svn_stringbuf_from_file2(&theirval,
-                                                   desc->their_abspath,
-                                                   subpool));
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                        _("They want to change the property value to '%s', "
-                          "you want to delete the property.\n"),
-                           theirval->data));
-                }
-            }
-        }
-      else
-        /* We don't recognize any other sort of conflict yet */
-        return SVN_NO_ERROR;
-
-      /* Diffing can happen between base and merged, to show conflict
-         markers to the user (this is the typical 3-way merge
-         scenario), or if no base is available, we can show a diff
-         between mine and theirs. */
-      if ((desc->merged_file && desc->base_abspath)
-          || (!desc->base_abspath && desc->my_abspath && desc->their_abspath))
-        diff_allowed = TRUE;
-
-      while (TRUE)
-        {
-          svn_pool_clear(subpool);
-
-          prompt = apr_pstrdup(subpool, _("Select: (p) postpone"));
-
-          if (diff_allowed)
-            {
-              prompt = apr_pstrcat(subpool, prompt,
-                                   _(", (df) diff-full, (e) edit, (m) merge"),
-                                   (char *)NULL);
-
-              if (knows_something)
-                prompt = apr_pstrcat(subpool, prompt, _(", (r) resolved"),
-                                     (char *)NULL);
-
-              if (! desc->is_binary &&
-                  desc->kind != svn_wc_conflict_kind_property)
-                prompt = apr_pstrcat(subpool, prompt,
-                                     _(",\n        (mc) mine-conflict, "
-                                       "(tc) theirs-conflict"),
-                                     (char *)NULL);
-            }
-          else
-            {
-              if (knows_something)
-                prompt = apr_pstrcat(subpool, prompt, _(", (r) resolved"),
-                                     (char *)NULL);
-              prompt = apr_pstrcat(subpool, prompt,
-                                   _(",\n        "
-                                     "(mf) mine-full, (tf) theirs-full"),
-                                   (char *)NULL);
-            }
-
-          prompt = apr_pstrcat(subpool, prompt, ",\n        ", (char *)NULL);
-          prompt = apr_pstrcat(subpool, prompt,
-                               _("(s) show all options: "),
-                               (char *)NULL);
-
-          SVN_ERR(svn_cmdline_prompt_user2(&answer, prompt, b->pb, subpool));
+       && (desc->reason == svn_wc_conflict_reason_edited)))
+    SVN_ERR(handle_text_conflict(*result, desc, b, subpool));
+  else if (desc->kind == svn_wc_conflict_kind_property)
+    SVN_ERR(handle_prop_conflict(*result, desc, b, subpool));
 
-          if (strcmp(answer, "s") == 0)
-            {
-              /* These are used in svn_cl__accept_from_word(). */
-              SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-              _("\n"
-                "  (e)  edit             - change merged file in an editor\n"
-                "  (df) diff-full        - show all changes made to merged "
-                                          "file\n"
-                "  (r)  resolved         - accept merged version of file\n"
-                "\n"
-                "  (dc) display-conflict - show all conflicts "
-                                          "(ignoring merged version)\n"
-                "  (mc) mine-conflict    - accept my version for all "
-                                          "conflicts (same)\n"
-                "  (tc) theirs-conflict  - accept their version for all "
-                                          "conflicts (same)\n"
-                "\n"
-                "  (mf) mine-full        - accept my version of entire file "
-                                          "(even non-conflicts)\n"
-                "  (tf) theirs-full      - accept their version of entire "
-                                          "file (same)\n"
-                "\n"
-                "  (p)  postpone         - mark the conflict to be "
-                                          "resolved later\n"
-                "  (m)  merge            - use internal merge tool to "
-                                          "resolve conflict\n"
-                "  (l)  launch           - launch external tool to "
-                                          "resolve conflict\n"
-                "  (s)  show all         - show this list\n\n")));
-            }
-          else if (strcmp(answer, "p") == 0 || strcmp(answer, ":-P") == 0)
-            {
-              /* Do nothing, let file be marked conflicted. */
-              (*result)->choice = svn_wc_conflict_choose_postpone;
-              break;
-            }
-          else if (strcmp(answer, "mc") == 0 || strcmp(answer, "X-)") == 0)
-            {
-              if (desc->is_binary)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; cannot choose "
-                                                "based on conflicts in a "
-                                                "binary file.\n\n")));
-                  continue;
-                }
-              else if (desc->kind == svn_wc_conflict_kind_property)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; cannot choose "
-                                                "based on conflicts for "
-                                                "properties.\n\n")));
-                  continue;
-                }
-
-              (*result)->choice = svn_wc_conflict_choose_mine_conflict;
-              if (performed_edit)
-                (*result)->save_merged = TRUE;
-              break;
-            }
-          else if (strcmp(answer, "tc") == 0 || strcmp(answer, "X-(") == 0)
-            {
-              if (desc->is_binary)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; cannot choose "
-                                                "based on conflicts in a "
-                                                "binary file.\n\n")));
-                  continue;
-                }
-              else if (desc->kind == svn_wc_conflict_kind_property)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; cannot choose "
-                                                "based on conflicts for "
-                                                "properties.\n\n")));
-                  continue;
-                }
-              (*result)->choice = svn_wc_conflict_choose_theirs_conflict;
-              if (performed_edit)
-                (*result)->save_merged = TRUE;
-              break;
-            }
-          else if (strcmp(answer, "mf") == 0 || strcmp(answer, ":-)") == 0)
-            {
-              (*result)->choice = svn_wc_conflict_choose_mine_full;
-              if (performed_edit)
-                (*result)->save_merged = TRUE;
-              break;
-            }
-          else if (strcmp(answer, "tf") == 0 || strcmp(answer, ":-(") == 0)
-            {
-              (*result)->choice = svn_wc_conflict_choose_theirs_full;
-              if (performed_edit)
-                (*result)->save_merged = TRUE;
-              break;
-            }
-          else if (strcmp(answer, "dc") == 0)
-            {
-              if (desc->is_binary)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; cannot "
-                                                "display conflicts for a "
-                                                "binary file.\n\n")));
-                  continue;
-                }
-              else if (desc->kind == svn_wc_conflict_kind_property)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; cannot "
-                                                "display conflicts for "
-                                                "properties.\n\n")));
-                  continue;
-                }
-              else if (! (desc->my_abspath && desc->base_abspath &&
-                          desc->their_abspath))
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; original "
-                                                "files not available.\n\n")));
-                  continue;
-                }
-              SVN_ERR(show_conflicts(desc, subpool));
-              knows_something = TRUE;
-            }
-          else if (strcmp(answer, "df") == 0)
-            {
-              if (! diff_allowed)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                 _("Invalid option; there's no "
-                                    "merged version to diff.\n\n")));
-                  continue;
-                }
-
-              SVN_ERR(show_diff(desc, subpool));
-              knows_something = TRUE;
-            }
-          else if (strcmp(answer, "e") == 0 || strcmp(answer, ":-E") == 0)
-            {
-              SVN_ERR(open_editor(&performed_edit, desc, b, subpool));
-              if (performed_edit)
-                knows_something = TRUE;
-            }
-          else if (strcmp(answer, "m") == 0 || strcmp(answer, ":-M") == 0)
-            {
-              if (desc->kind != svn_wc_conflict_kind_text)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; can only "
-                                                "resolve text conflicts with "
-                                                "the internal merge tool."
-                                                "\n\n")));
-                  continue;
-                }
-
-              if (desc->base_abspath && desc->their_abspath &&
-                  desc->my_abspath && desc->merged_file)
-                {
-                  svn_boolean_t remains_in_conflict;
-
-                  SVN_ERR(svn_cl__merge_file(desc->base_abspath,
-                                             desc->their_abspath,
-                                             desc->my_abspath,
-                                             desc->merged_file,
-                                             desc->local_abspath,
-                                             b->editor_cmd,
-                                             b->config,
-                                             &remains_in_conflict,
-                                             subpool));
-                  knows_something = !remains_in_conflict;
-                }
-              else
-                SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                            _("Invalid option.\n\n")));
-            }
-          else if (strcmp(answer, "l") == 0 || strcmp(answer, ":-l") == 0)
-            {
-              if (desc->kind == svn_wc_conflict_kind_property)
-                {
-                  SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                              _("Invalid option; cannot "
-                                                "resolve property conflicts "
-                                                "with an external merge tool."
-                                                "\n\n")));
-                  continue;
-                }
-              if (desc->base_abspath && desc->their_abspath &&
-                  desc->my_abspath && desc->merged_file)
-                {
-                  SVN_ERR(launch_resolver(&performed_edit, desc, b, subpool));
-                  if (performed_edit)
-                    knows_something = TRUE;
-                }
-              else
-                SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                            _("Invalid option.\n\n")));
-            }
-          else if (strcmp(answer, "r") == 0)
-            {
-              /* We only allow the user accept the merged version of
-                 the file if they've edited it, or at least looked at
-                 the diff. */
-              if (knows_something)
-                {
-                  (*result)->choice = svn_wc_conflict_choose_merged;
-                  break;
-                }
-              else
-                SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-                                            _("Invalid option.\n\n")));
-            }
-        }
-    }
   /*
     Dealing with obstruction of additions can be tricky.  The
     obstructing item could be unversioned, versioned, or even
@@ -767,7 +804,7 @@ svn_cl__conflict_handler(svn_wc_conflict
                                                      desc->local_abspath,
                                                      subpool)));
       prompt = _("Select: (p) postpone, (mf) mine-full, "
-                 "(tf) theirs-full, (h) help:");
+                 "(tf) theirs-full, (h) help: ");
 
       while (1)
         {
@@ -819,7 +856,9 @@ svn_cl__conflict_handler(svn_wc_conflict
                                                      scratch_pool),
                    readable_desc));
 
-      prompt = _("Select: (p) postpone, (r) mark-resolved, (h) help: ");
+      prompt = _("Select: (p) postpone, (r) mark-resolved, "
+                 "(mc) mine-conflict,\n"
+                 "        (tc) theirs-conflict, (h) help: ");
 
       while (1)
         {
@@ -830,8 +869,10 @@ svn_cl__conflict_handler(svn_wc_conflict
           if (strcmp(answer, "h") == 0 || strcmp(answer, "?") == 0)
             {
               SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
-              _("  (p) postpone      - resolve the conflict later\n"
-                "  (r) resolved      - accept current working tree\n")));
+              _("  (p) postpone         - resolve the conflict later\n"
+                "  (r) resolved         - accept current working copy state\n"
+                "  (mc) mine-conflict   - prefer local change\n"
+                "  (tc) theirs-conflict - prefer incoming change\n")));
             }
           if (strcmp(answer, "p") == 0 || strcmp(answer, ":-p") == 0)
             {
@@ -843,6 +884,16 @@ svn_cl__conflict_handler(svn_wc_conflict
               (*result)->choice = svn_wc_conflict_choose_merged;
               break;
             }
+          else if (strcmp(answer, "mc") == 0)
+            {
+              (*result)->choice = svn_wc_conflict_choose_mine_conflict;
+              break;
+            }
+          else if (strcmp(answer, "tc") == 0)
+            {
+              (*result)->choice = svn_wc_conflict_choose_theirs_conflict;
+              break;
+            }
         }
     }
 
@@ -855,16 +906,77 @@ svn_cl__conflict_handler(svn_wc_conflict
   return SVN_NO_ERROR;
 }
 
+/* Implement svn_wc_conflict_resolver_func2_t; postpones all conflicts
+ * and remembers conflicted paths in BATON. */
 svn_error_t *
-svn_cl__resolve_conflicts(apr_array_header_t *targets,
-                          svn_depth_t depth,
-                          const svn_cl__opt_state_t *opt_state,
-                          svn_client_ctx_t *ctx,
-                          apr_pool_t *scratch_pool)
+svn_cl__conflict_func_postpone(svn_wc_conflict_result_t **result,
+                               const svn_wc_conflict_description2_t *desc,
+                               void *baton,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool)
+{
+  apr_hash_t *conflicted_paths = baton;
+  
+  apr_hash_set(conflicted_paths,
+               apr_pstrdup(apr_hash_pool_get(conflicted_paths),
+                           desc->local_abspath),
+               APR_HASH_KEY_STRING, "");
+
+  *result = svn_wc_create_conflict_result(svn_wc_conflict_choose_postpone,
+                                          NULL, result_pool);
+  return SVN_NO_ERROR;
+}
+
+void *
+svn_cl__get_conflict_func_postpone_baton(apr_pool_t *result_pool)
+{
+  return apr_hash_make(result_pool);
+}
+
+static apr_array_header_t *
+get_postponed_conflicted_paths(void *baton, apr_pool_t *result_pool)
 {
+  apr_hash_t *conflicted_paths = baton;
+  apr_array_header_t *sorted_array;
+  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));
+  result_array = apr_array_make(result_pool, sorted_array->nelts,
+                                sizeof(const char *));
+  for (i = 0; i < sorted_array->nelts; i++)
+    {
+      svn_sort__item_t item;
+      
+      item = APR_ARRAY_IDX(sorted_array, i, svn_sort__item_t);
+      APR_ARRAY_PUSH(result_array, const char *) = apr_pstrdup(result_pool,
+                                                               item.key);
+    }
+
+  return result_array;
+}
+
+svn_error_t *
+svn_cl__resolve_postponed_conflicts(void *baton,
+                                    svn_depth_t depth,
+                                    svn_cl__accept_t accept_which,
+                                    const char *editor_cmd,
+                                    svn_client_ctx_t *ctx,
+                                    apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *targets;
   int i;
   apr_pool_t *iterpool;
 
+  targets = get_postponed_conflicted_paths(baton, scratch_pool);
+  if (targets == NULL)
+    return SVN_NO_ERROR;
+
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < targets->nelts; i++)
     {
@@ -873,19 +985,25 @@ svn_cl__resolve_conflicts(apr_array_head
       const char *local_abspath;
       svn_wc_conflict_resolver_func2_t conflict_func2;
       void *conflict_baton2;
+      svn_cl__interactive_conflict_baton_t *b;
 
       svn_pool_clear(iterpool);
 
       SVN_ERR(svn_dirent_get_absolute(&local_abspath, target, iterpool));
 
-
       /* Store old state */
       conflict_func2 = ctx->conflict_func2;
       conflict_baton2 = ctx->conflict_baton2;
 
-      /* Store interactive resolver */
-      ctx->conflict_func2 = opt_state->conflict_func;
-      ctx->conflict_baton2 = opt_state->conflict_baton;
+      /* Set up the interactive resolver. */
+      ctx->conflict_func2 = svn_cl__conflict_func_interactive;
+      SVN_ERR(svn_cl__get_conflict_func_interactive_baton(&b, accept_which,
+                                                          ctx->config,
+                                                          editor_cmd,
+                                                          ctx->cancel_func,
+                                                          ctx->cancel_baton,
+                                                          scratch_pool));
+      ctx->conflict_baton2 = b;
 
       err = svn_client_resolve(local_abspath, depth,
                                svn_wc_conflict_choose_unspecified,

Modified: subversion/branches/ev2-export/subversion/svn/file-merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/file-merge.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/file-merge.c (original)
+++ subversion/branches/ev2-export/subversion/svn/file-merge.c Sun Oct 21 02:00:31 2012
@@ -43,6 +43,10 @@
 #include <sys/ioctl.h>
 #endif
 
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #include <fcntl.h>
 #include <stdlib.h>
 
@@ -309,8 +313,11 @@ get_term_width(void)
   if (fd != -1)
     {
       struct winsize ws;
+      int error;
 
-      if (ioctl(fd, TIOCGWINSZ, &ws) != -1)
+      error = ioctl(fd, TIOCGWINSZ, &ws);
+      close(fd);
+      if (error != -1)
         {
           if (ws.ws_col < 80)
             return 80;
@@ -358,7 +365,7 @@ static const char *
 prepare_line_for_display(const char *line, apr_pool_t *pool)
 {
   svn_stringbuf_t *buf = svn_stringbuf_create(line, pool);
-  int width;
+  size_t width;
   int line_width = LINE_DISPLAY_WIDTH;
   apr_pool_t *iterpool;
 
@@ -589,7 +596,7 @@ merge_chunks(apr_array_header_t **merged
 
   prompt = svn_stringbuf_create(
              apr_psprintf(scratch_pool, "%s\n%s|%s\n%s",
-                          _("Conflicting section found during merge."),
+                          _("Conflicting section found during merge:"),
                           prepare_line_for_display(
                             apr_psprintf(scratch_pool,
                                          _("(1) their version (at line %lu)"),
@@ -651,7 +658,7 @@ merge_chunks(apr_array_header_t **merged
       "        (e2) edit your version and use the result,\n"
       "        (eb) edit both versions and use the result,\n"
       "        (p) postpone this conflicting section leaving conflict markers,\n"
-      "        (a) abort entire merge and return to main menu: "));
+      "        (a) abort file merge and return to main menu: "));
 
   /* Now let's see what the user wants to do with this conflict. */
   while (TRUE)
@@ -830,6 +837,7 @@ svn_cl__merge_file(const char *base_path
                    const char *my_path,
                    const char *merged_path,
                    const char *wc_path,
+                   const char *path_prefix,
                    const char *editor_cmd,
                    apr_hash_t *config,
                    svn_boolean_t *remains_in_conflict,
@@ -843,6 +851,14 @@ svn_cl__merge_file(const char *base_path
   apr_file_t *merged_file;
   const char *merged_file_name;
   struct file_merge_baton fmb;
+  svn_boolean_t executable;
+
+
+  SVN_ERR(svn_cmdline_printf(
+            scratch_pool, _("Merging '%s'.\n"),
+            svn_dirent_local_style(svn_dirent_skip_ancestor(path_prefix,
+                                                            wc_path),
+                                   scratch_pool)));
 
   SVN_ERR(svn_io_file_open(&original_file, base_path,
                            APR_READ|APR_BUFFERED|APR_BINARY,
@@ -881,23 +897,58 @@ svn_cl__merge_file(const char *base_path
   SVN_ERR(svn_io_file_close(latest_file, scratch_pool));
   SVN_ERR(svn_io_file_close(merged_file, scratch_pool));
 
+  /* Start out assuming that conflicts remain. */
   if (remains_in_conflict)
-    *remains_in_conflict = (fmb.remains_in_conflict || fmb.abort_merge);
+    *remains_in_conflict = TRUE;
 
   if (fmb.abort_merge)
     {
       SVN_ERR(svn_io_remove_file2(merged_file_name, TRUE, scratch_pool));
+      SVN_ERR(svn_cmdline_printf(
+                scratch_pool, _("Merge of '%s' aborted.\n"),
+                svn_dirent_local_style(svn_dirent_skip_ancestor(path_prefix,
+                                                                wc_path),
+                                       scratch_pool)));
+                
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR_W(svn_io_file_move(merged_file_name, merged_path, scratch_pool),
+  SVN_ERR(svn_io_is_file_executable(&executable, merged_path, scratch_pool));
+  SVN_ERR_W(svn_io_copy_file(merged_file_name, merged_path, FALSE,
+                             scratch_pool),
             apr_psprintf(scratch_pool,
-                         _("Could not write merged result to '%s', "
-                         "saved instead at '%s'.\n"),
-                         svn_dirent_local_style(merged_path,
-                                                scratch_pool),
+                         _("Could not write merged result to '%s', saved "
+                           "instead at '%s'.\n'%s' remains in conflict.\n"),
+                         svn_dirent_local_style(
+                           svn_dirent_skip_ancestor(path_prefix, merged_path),
+                           scratch_pool),
                          svn_dirent_local_style(merged_file_name,
-                                                scratch_pool)));
+                                                scratch_pool),
+                         svn_dirent_local_style(
+                           svn_dirent_skip_ancestor(path_prefix, wc_path),
+                           scratch_pool)));
+  SVN_ERR(svn_io_set_file_executable(merged_path, executable, FALSE,
+                                     scratch_pool));
+  SVN_ERR(svn_io_remove_file2(merged_file_name, TRUE, scratch_pool));
+
+  /* The merge was not aborted and we could install the merged result. The
+   * file remains in conflict unless all conflicting sections were resolved. */
+  if (remains_in_conflict)
+    *remains_in_conflict = fmb.remains_in_conflict;
 
+  if (fmb.remains_in_conflict)
+    SVN_ERR(svn_cmdline_printf(
+              scratch_pool,
+              _("Merge of '%s' completed (remains in conflict).\n"),
+              svn_dirent_local_style(svn_dirent_skip_ancestor(path_prefix,
+                                                              wc_path),
+                                     scratch_pool)));
+  else
+    SVN_ERR(svn_cmdline_printf(
+              scratch_pool, _("Merge of '%s' completed.\n"),
+              svn_dirent_local_style(svn_dirent_skip_ancestor(path_prefix,
+                                                              wc_path),
+                                     scratch_pool)));
+                
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ev2-export/subversion/svn/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/help-cmd.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/help-cmd.c (original)
+++ subversion/branches/ev2-export/subversion/svn/help-cmd.c Sun Oct 21 02:00:31 2012
@@ -79,10 +79,11 @@ svn_cl__help(apr_getopt_t *os,
   version_footer = svn_stringbuf_create(ra_desc_start, pool);
   SVN_ERR(svn_ra_print_modules(version_footer, pool));
 
-  return svn_opt_print_help3(os,
+  return svn_opt_print_help4(os,
                              "svn",   /* ### erm, derive somehow? */
                              opt_state ? opt_state->version : FALSE,
                              opt_state ? opt_state->quiet : FALSE,
+                             opt_state ? opt_state->verbose : FALSE,
                              version_footer->data,
                              help_header,   /* already gettext()'d */
                              svn_cl__cmd_table,

Modified: subversion/branches/ev2-export/subversion/svn/log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/svn/log-cmd.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/svn/log-cmd.c (original)
+++ subversion/branches/ev2-export/subversion/svn/log-cmd.c Sun Oct 21 02:00:31 2012
@@ -71,10 +71,9 @@ struct log_receiver_baton
   /* Stack which keeps track of merge revision nesting, using svn_revnum_t's */
   apr_array_header_t *merge_stack;
 
-  /* Log message search pattern. Log entries will only be shown if the author,
-   * the log message, or a changed path matches this pattern. */
-  const char *search_pattern;
-  svn_boolean_t case_insensitive_search;
+  /* Log message search patterns. Log entries will only be shown if the author,
+   * the log message, or a changed path matches one of these patterns. */
+  apr_array_header_t *search_patterns;
 
   /* Pool for persistent allocations. */
   apr_pool_t *pool;
@@ -123,7 +122,7 @@ display_diff(const svn_log_entry_t *log_
   end_revision.kind = svn_opt_revision_number;
   end_revision.value.number = log_entry->revision;
 
-  SVN_ERR(svn_stream_puts(outstream, _("\n")));
+  SVN_ERR(svn_stream_puts(outstream, "\n"));
   SVN_ERR(svn_client_diff_peg6(diff_options,
                                target_path_or_url,
                                target_peg_revision,
@@ -156,12 +155,11 @@ match_search_pattern(const char *search_
                      const char *date,
                      const char *log_message,
                      apr_hash_t *changed_paths,
-                     svn_boolean_t case_insensitive_search,
                      apr_pool_t *pool)
 {
   /* Match any substring containing the pattern, like UNIX 'grep' does. */
   const char *pattern = apr_psprintf(pool, "*%s*", search_pattern);
-  int flags = (case_insensitive_search ? APR_FNM_CASE_BLIND : 0);
+  int flags = APR_FNM_CASE_BLIND;
 
   /* Does the author match the search pattern? */
   if (author && apr_fnmatch(pattern, author, flags) == APR_SUCCESS)
@@ -203,6 +201,50 @@ match_search_pattern(const char *search_
   return FALSE;
 }
 
+/* Match all search patterns in SEARCH_PATTERNS against AUTHOR, DATE, MESSAGE,
+ * and CHANGED_PATHS. Return TRUE if any pattern matches, else FALSE.
+ * SCRACH_POOL is used for temporary allocations. */
+static svn_boolean_t
+match_search_patterns(apr_array_header_t *search_patterns,
+                      const char *author,
+                      const char *date,
+                      const char *message,
+                      apr_hash_t *changed_paths,
+                      apr_pool_t *scratch_pool)
+{
+  int i;
+  svn_boolean_t match = FALSE;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  for (i = 0; i < search_patterns->nelts; i++)
+    {
+      apr_array_header_t *pattern_group;
+      int j;
+
+      pattern_group = APR_ARRAY_IDX(search_patterns, i, apr_array_header_t *);
+
+      /* All patterns within the group must match. */
+      for (j = 0; j < pattern_group->nelts; j++)
+        {
+          const char *pattern;
+
+          svn_pool_clear(iterpool);
+          
+          pattern = APR_ARRAY_IDX(pattern_group, j, const char *);
+          match = match_search_pattern(pattern, author, date, message,
+                                       changed_paths, iterpool);
+          if (!match)
+            break;
+        }
+
+      match = (match && j == pattern_group->nelts);
+      if (match)
+        break;
+    }
+  svn_pool_destroy(iterpool);
+
+  return match;
+}
 
 /* Implement `svn_log_entry_receiver_t', printing the logs in
  * a human-readable and machine-parseable format.
@@ -320,10 +362,9 @@ log_entry_receiver(void *baton,
   if (! lb->omit_log_message && message == NULL)
     message = "";
 
-  if (lb->search_pattern &&
-      ! match_search_pattern(lb->search_pattern, author, date, message,
-                             log_entry->changed_paths2,
-                             lb->case_insensitive_search, pool))
+  if (lb->search_patterns &&
+      ! match_search_patterns(lb->search_patterns, author, date, message,
+                              log_entry->changed_paths2, pool))
     {
       if (log_entry->has_children)
         APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
@@ -505,10 +546,9 @@ log_entry_receiver_xml(void *baton,
     }
 
   /* Match search pattern before XML-escaping. */
-  if (lb->search_pattern &&
-      ! match_search_pattern(lb->search_pattern, author, date, message,
-                             log_entry->changed_paths2,
-                             lb->case_insensitive_search, pool))
+  if (lb->search_patterns &&
+      ! match_search_patterns(lb->search_patterns, author, date, message,
+                              log_entry->changed_paths2, pool))
     {
       if (log_entry->has_children)
         APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
@@ -586,7 +626,13 @@ log_entry_receiver_xml(void *baton,
               /* <path action="X"> */
               svn_xml_make_open_tag(&sb, pool, svn_xml_protect_pcdata, "path",
                                     "action", action,
-                                    "kind", svn_cl__node_kind_str_xml(log_item->node_kind), NULL);
+                                    "kind", svn_cl__node_kind_str_xml(
+                                                     log_item->node_kind),
+                                    "text-mods", svn_tristate__to_word(
+                                                     log_item->text_modified),
+                                    "prop-mods", svn_tristate__to_word(
+                                                     log_item->props_modified),
+                                    NULL);
             }
           /* xxx</path> */
           svn_xml_escape_cdata_cstring(&sb, path, pool);
@@ -609,7 +655,7 @@ log_entry_receiver_xml(void *baton,
       svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops", NULL);
       SVN_ERR(svn_cl__print_xml_prop_hash(&sb, log_entry->revprops,
                                           FALSE, /* name_only */
-                                          pool));
+                                          FALSE, pool));
       svn_xml_make_close_tag(&sb, pool, "revprops");
     }
 
@@ -740,8 +786,7 @@ svn_cl__log(apr_getopt_t *os,
                                                    : opt_state->depth;
   lb.diff_extensions = opt_state->extensions;
   lb.merge_stack = apr_array_make(pool, 0, sizeof(svn_revnum_t));
-  lb.search_pattern = opt_state->search_pattern;
-  lb.case_insensitive_search = opt_state->case_insensitive_search;
+  lb.search_patterns = opt_state->search_patterns;
   lb.pool = pool;
 
   if (opt_state->xml)