subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From as...@apache.org
Subject svn commit: r1413258 [23/33] - in /subversion/branches/compressed-pristines: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/ notes/ notes/directory-index/ subversion/ subv...
Date Sat, 24 Nov 2012 20:29:48 GMT
Modified: subversion/branches/compressed-pristines/subversion/po/zh_TW.po
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/po/zh_TW.po?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/po/zh_TW.po [UTF-8] (original)
+++ subversion/branches/compressed-pristines/subversion/po/zh_TW.po [UTF-8] Sat Nov 24 20:29:11 2012
@@ -12810,7 +12810,7 @@ msgstr ""
 #~ "                                '{' DATE '}' 該日開始的修訂版\n"
 #~ "                                'HEAD'       檔案庫最新版本\n"
 #~ "                                'BASE'       該項目工作複本的基礎修訂版\n"
-#~ "                                'COMMITED'   位於或早於 BASE 的最後送交\n"
+#~ "                                'COMMITTED'  位於或早於 BASE 的最後送交\n"
 #~ "                                'PREV'       COMMITTED 之前的修訂版"
 
 #~ msgid "Error reading administrative log file in '%s'"

Modified: subversion/branches/compressed-pristines/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/svn/cl.h?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/svn/cl.h (original)
+++ subversion/branches/compressed-pristines/subversion/svn/cl.h Sat Nov 24 20:29:11 2012
@@ -236,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;
 
 
@@ -333,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. ***/
@@ -460,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
@@ -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/compressed-pristines/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/svn/conflict-callbacks.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/compressed-pristines/subversion/svn/conflict-callbacks.c Sat Nov 24 20:29:11 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,333 +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->path_prefix,
-                                             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
@@ -768,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)
         {
@@ -820,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)
         {
@@ -831,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)
             {
@@ -844,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;
+            }
         }
     }
 
@@ -856,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++)
     {
@@ -874,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/compressed-pristines/subversion/svn/file-merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/svn/file-merge.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/svn/file-merge.c (original)
+++ subversion/branches/compressed-pristines/subversion/svn/file-merge.c Sat Nov 24 20:29:11 2012
@@ -365,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;
 
@@ -596,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)"),
@@ -851,6 +851,7 @@ 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(
@@ -912,7 +913,9 @@ svn_cl__merge_file(const char *base_path
       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'%s' remains in conflict.\n"),
@@ -924,6 +927,9 @@ svn_cl__merge_file(const char *base_path
                          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. */

Modified: subversion/branches/compressed-pristines/subversion/svn/log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/svn/log-cmd.c?rev=1413258&r1=1413257&r2=1413258&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/svn/log-cmd.c (original)
+++ subversion/branches/compressed-pristines/subversion/svn/log-cmd.c Sat Nov 24 20:29:11 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;
@@ -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)



Mime
View raw message