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)