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)
