Modified: subversion/branches/ra-git/subversion/svn/info-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/info-cmd.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/info-cmd.c (original) +++ subversion/branches/ra-git/subversion/svn/info-cmd.c Tue Oct 11 09:11:50 2016 @@ -162,6 +162,9 @@ typedef struct print_info_baton_t /* Did we already print a line of output? */ svn_boolean_t start_new_line; + + /* The client context. */ + svn_client_ctx_t *ctx; } print_info_baton_t; @@ -403,9 +406,9 @@ print_info_xml(void *baton, svn_pool_clear(iterpool); - SVN_ERR(svn_client_conflict_from_wc_description2_t(&conflict, desc, - iterpool, - iterpool)); + SVN_ERR(svn_client_conflict_get(&conflict, desc->local_abspath, + receiver_baton->ctx, + iterpool, iterpool)); SVN_ERR(svn_cl__append_conflict_info_xml(sb, conflict, iterpool)); } svn_pool_destroy(iterpool); @@ -592,87 +595,86 @@ print_info(void *baton, { svn_boolean_t printed_tc = FALSE; svn_stringbuf_t *conflicted_props = NULL; - int i; - apr_pool_t *iterpool; - - iterpool = svn_pool_create(pool); - for (i = 0; i < info->wc_info->conflicts->nelts; i++) + svn_client_conflict_t *conflict; + svn_boolean_t text_conflicted; + apr_array_header_t *props_conflicted; + svn_boolean_t tree_conflicted; + const svn_wc_conflict_description2_t *desc2 = + APR_ARRAY_IDX(info->wc_info->conflicts, 0, + const svn_wc_conflict_description2_t *); + + SVN_ERR(svn_client_conflict_get(&conflict, desc2->local_abspath, + receiver_baton->ctx, pool, pool)); + SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, + &props_conflicted, + &tree_conflicted, + conflict, pool, pool)); + if (text_conflicted) { - const svn_wc_conflict_description2_t *desc2 = - APR_ARRAY_IDX(info->wc_info->conflicts, i, - const svn_wc_conflict_description2_t *); - const char *desc; const char *base_abspath = NULL; const char *my_abspath = NULL; const char *their_abspath = NULL; - svn_client_conflict_t *conflict; - svn_pool_clear(iterpool); + SVN_ERR(svn_client_conflict_text_get_contents( + NULL, &my_abspath, &base_abspath, &their_abspath, + conflict, pool, pool)); + + if (base_abspath) + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict Previous Base File: %s\n"), + svn_cl__local_style_skip_ancestor( + receiver_baton->path_prefix, + base_abspath, + pool))); + + if (my_abspath) + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict Previous Working File: %s\n"), + svn_cl__local_style_skip_ancestor( + receiver_baton->path_prefix, + my_abspath, + pool))); + + if (their_abspath) + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict Current Base File: %s\n"), + svn_cl__local_style_skip_ancestor( + receiver_baton->path_prefix, + their_abspath, + pool))); + } - SVN_ERR(svn_client_conflict_from_wc_description2_t(&conflict, - desc2, - iterpool, - iterpool)); - switch (svn_client_conflict_get_kind(conflict)) - { - case svn_wc_conflict_kind_text: + if (props_conflicted) + { + int i; - SVN_ERR(svn_client_conflict_text_get_contents( - NULL, &my_abspath, &base_abspath, &their_abspath, - conflict, pool, pool)); - - if (base_abspath) - SVN_ERR(svn_cmdline_printf(pool, - _("Conflict Previous Base File: %s\n"), - svn_cl__local_style_skip_ancestor( - receiver_baton->path_prefix, - base_abspath, - pool))); - - if (my_abspath) - SVN_ERR(svn_cmdline_printf(pool, - _("Conflict Previous Working File: %s\n"), - svn_cl__local_style_skip_ancestor( - receiver_baton->path_prefix, - my_abspath, - pool))); - - if (their_abspath) - SVN_ERR(svn_cmdline_printf(pool, - _("Conflict Current Base File: %s\n"), - svn_cl__local_style_skip_ancestor( - receiver_baton->path_prefix, - their_abspath, - pool))); - break; + for (i = 0; i < props_conflicted->nelts; i++) + { + const char *name; - case svn_wc_conflict_kind_property: + name = APR_ARRAY_IDX(props_conflicted, i, const char *); + if (conflicted_props == NULL) + conflicted_props = svn_stringbuf_create(name, pool); + else { - const char *name; - - name = svn_client_conflict_prop_get_propname(conflict); - if (conflicted_props == NULL) - conflicted_props = svn_stringbuf_create(name, pool); - else - { - svn_stringbuf_appendbyte(conflicted_props, ' '); - svn_stringbuf_appendcstr(conflicted_props, name); - } + svn_stringbuf_appendbyte(conflicted_props, ' '); + svn_stringbuf_appendcstr(conflicted_props, name); } - break; - - case svn_wc_conflict_kind_tree: - printed_tc = TRUE; - SVN_ERR( - svn_cl__get_human_readable_tree_conflict_description( - &desc, conflict, pool)); - - SVN_ERR(svn_cmdline_printf(pool, "%s: %s\n", - _("Tree conflict"), desc)); - break; } } - svn_pool_destroy(iterpool); + + if (tree_conflicted) + { + const char *desc; + + printed_tc = TRUE; + SVN_ERR( + svn_cl__get_human_readable_tree_conflict_description( + &desc, conflict, pool)); + + SVN_ERR(svn_cmdline_printf(pool, "%s: %s\n", + _("Tree conflict"), desc)); + } if (conflicted_props) SVN_ERR(svn_cmdline_printf(pool, _("Conflicted Properties: %s\n"), @@ -689,14 +691,7 @@ print_info(void *baton, const char *repos_relpath; svn_revnum_t peg_rev; svn_node_kind_t node_kind; - const svn_wc_conflict_description2_t *desc2 = - APR_ARRAY_IDX(info->wc_info->conflicts, 0, - const svn_wc_conflict_description2_t *); - svn_client_conflict_t *conflict; - - SVN_ERR(svn_client_conflict_from_wc_description2_t(&conflict, desc2, - pool, pool)); if (!printed_tc) { const char *desc; @@ -926,6 +921,8 @@ svn_cl__info(apr_getopt_t *os, /* Add "." if user passed 0 arguments. */ svn_opt_push_implicit_dot_target(targets, pool); + receiver_baton.ctx = ctx; + if (opt_state->xml) { receiver = print_info_xml;
Modified: subversion/branches/ra-git/subversion/svn/log-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/log-cmd.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/log-cmd.c (original) +++ subversion/branches/ra-git/subversion/svn/log-cmd.c Tue Oct 11 09:11:50 2016 @@ -38,6 +38,7 @@ #include "private/svn_cmdline_private.h" #include "private/svn_sorts_private.h" +#include "private/svn_utf_private.h" #include "cl.h" #include "cl-log.h" @@ -110,6 +111,24 @@ display_diff(const svn_log_entry_t *log_ return SVN_NO_ERROR; } +/* Return TRUE if STR matches PATTERN. Else, return FALSE. Assumes that + * PATTERN is a UTF-8 string prepared for case- and accent-insensitive + * comparison via svn_utf__xfrm(). */ +static svn_boolean_t +match(const char *pattern, const char *str, svn_membuf_t *buf) +{ + svn_error_t *err; + + err = svn_utf__xfrm(&str, str, strlen(str), TRUE, TRUE, buf); + if (err) + { + /* Can't match invalid data. */ + svn_error_clear(err); + return FALSE; + } + + return apr_fnmatch(pattern, str, 0) == APR_SUCCESS; +} /* Return TRUE if SEARCH_PATTERN matches the AUTHOR, DATE, LOG_MESSAGE, * or a path in the set of keys of the CHANGED_PATHS hash. Else, return FALSE. @@ -120,22 +139,22 @@ match_search_pattern(const char *search_ const char *date, const char *log_message, apr_hash_t *changed_paths, + svn_membuf_t *buf, 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 = 0; /* Does the author match the search pattern? */ - if (author && apr_fnmatch(pattern, author, flags) == APR_SUCCESS) + if (author && match(pattern, author, buf)) return TRUE; /* Does the date the search pattern? */ - if (date && apr_fnmatch(pattern, date, flags) == APR_SUCCESS) + if (date && match(pattern, date, buf)) return TRUE; /* Does the log message the search pattern? */ - if (log_message && apr_fnmatch(pattern, log_message, flags) == APR_SUCCESS) + if (log_message && match(pattern, log_message, buf)) return TRUE; if (changed_paths) @@ -150,15 +169,14 @@ match_search_pattern(const char *search_ const char *path = apr_hash_this_key(hi); svn_log_changed_path2_t *log_item; - if (apr_fnmatch(pattern, path, flags) == APR_SUCCESS) + if (match(pattern, path, buf)) return TRUE; /* Match copy-from paths, too. */ log_item = apr_hash_this_val(hi); if (log_item->copyfrom_path && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev) - && apr_fnmatch(pattern, - log_item->copyfrom_path, flags) == APR_SUCCESS) + && match(pattern, log_item->copyfrom_path, buf)) return TRUE; } } @@ -168,13 +186,14 @@ match_search_pattern(const char *search_ /* 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. */ + * BUF and SCRATCH_POOL are 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, + svn_membuf_t *buf, apr_pool_t *scratch_pool) { int i; @@ -197,7 +216,7 @@ match_search_patterns(apr_array_header_t pattern = APR_ARRAY_IDX(pattern_group, j, const char *); match = match_search_pattern(pattern, author, date, message, - changed_paths, iterpool); + changed_paths, buf, iterpool); if (!match) break; } @@ -331,7 +350,7 @@ svn_cl__log_entry_receiver(void *baton, if (lb->search_patterns && ! match_search_patterns(lb->search_patterns, author, date, message, - log_entry->changed_paths2, pool)) + log_entry->changed_paths2, &lb->buffer, pool)) { if (log_entry->has_children) { @@ -535,7 +554,7 @@ svn_cl__log_entry_receiver_xml(void *bat /* Match search pattern before XML-escaping. */ if (lb->search_patterns && ! match_search_patterns(lb->search_patterns, author, date, message, - log_entry->changed_paths2, pool)) + log_entry->changed_paths2, &lb->buffer, pool)) { if (log_entry->has_children) { @@ -795,6 +814,7 @@ svn_cl__log(apr_getopt_t *os, lb.diff_extensions = opt_state->extensions; lb.merge_stack = NULL; lb.search_patterns = opt_state->search_patterns; + svn_membuf__create(&lb.buffer, 0, pool); lb.pool = pool; if (opt_state->xml) Modified: subversion/branches/ra-git/subversion/svn/merge-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/merge-cmd.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/merge-cmd.c (original) +++ subversion/branches/ra-git/subversion/svn/merge-cmd.c Tue Oct 11 09:11:50 2016 @@ -123,6 +123,11 @@ run_merge(svn_boolean_t two_sources_spec _("Merge sources must both be " "either paths or URLs")); + if (svn_path_is_url(targetpath)) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Merge target '%s' must be a local path " + "but looks like a URL"), targetpath); + if (opt_state->verbose) SVN_ERR(svn_cmdline_printf(scratch_pool, _("--- Merging\n"))); merge_err = svn_client_merge5(sourcepath1, @@ -145,6 +150,84 @@ run_merge(svn_boolean_t two_sources_spec return merge_err; } +/* Baton type for conflict_func_merge_cmd(). */ +struct conflict_func_merge_cmd_baton { + svn_cl__accept_t accept_which; + const char *path_prefix; + svn_cl__conflict_stats_t *conflict_stats; +}; + +/* This implements the `svn_wc_conflict_resolver_func2_t ' interface. + * + * The merge subcommand needs to install this legacy conflict callback + * in case the user passed an --accept option to 'svn merge'. + * Otherwise, merges involving multiple editor drives might encounter a + * conflict during one of the editor drives and abort with an error, + * rather than resolving conflicts as per the --accept option and + * continuing with the next editor drive. + * ### TODO add an svn_client_merge API that makes this callback unnecessary + */ +static svn_error_t * +conflict_func_merge_cmd(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) +{ + struct conflict_func_merge_cmd_baton *b = baton; + svn_wc_conflict_choice_t choice; + + switch (b->accept_which) + { + case svn_cl__accept_postpone: + case svn_cl__accept_invalid: + case svn_cl__accept_unspecified: + /* Postpone or no valid --accept option, postpone the conflict. */ + choice = svn_wc_conflict_choose_postpone; + break; + case svn_cl__accept_base: + choice = svn_wc_conflict_choose_base; + break; + case svn_cl__accept_working: + choice = svn_wc_conflict_choose_merged; + break; + case svn_cl__accept_mine_conflict: + choice = svn_wc_conflict_choose_mine_conflict; + break; + case svn_cl__accept_theirs_conflict: + choice = svn_wc_conflict_choose_theirs_conflict; + break; + case svn_cl__accept_mine_full: + choice = svn_wc_conflict_choose_mine_full; + break; + case svn_cl__accept_theirs_full: + choice = svn_wc_conflict_choose_theirs_full; + break; + case svn_cl__accept_edit: + case svn_cl__accept_launch: + /* The 'edit' and 'launch' options used to be valid in Subversion 1.9 but + * we can't support these options for the purposes of this callback. */ + choice = svn_wc_conflict_choose_postpone; + break; + } + + *result = svn_wc_create_conflict_result(choice, NULL, result_pool); + + /* If we are resolving a conflict, adjust the summary of conflicts. */ + if (choice != svn_wc_conflict_choose_postpone) + { + const char *local_path; + + local_path = svn_cl__local_style_skip_ancestor(b->path_prefix, + desc->local_abspath, + scratch_pool); + svn_cl__conflict_stats_resolved(b->conflict_stats, local_path, + desc->kind); + } + + return SVN_NO_ERROR; +} + /* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__merge(apr_getopt_t *os, @@ -152,6 +235,8 @@ svn_cl__merge(apr_getopt_t *os, apr_pool_t *pool) { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; apr_array_header_t *targets; const char *sourcepath1 = NULL, *sourcepath2 = NULL, *targetpath = ""; @@ -160,6 +245,7 @@ svn_cl__merge(apr_getopt_t *os, svn_opt_revision_t first_range_start, first_range_end, peg_revision1, peg_revision2; apr_array_header_t *options, *ranges_to_merge = opt_state->revision_ranges; + apr_array_header_t *conflicted_paths; svn_boolean_t has_explicit_target = FALSE; /* Merge doesn't support specifying a revision or revision range @@ -427,6 +513,21 @@ svn_cl__merge(apr_getopt_t *os, "with --reintegrate")); } + /* Install a legacy conflict handler if the --accept option was given. + * Else, svn_client_merge5() may abort the merge in an undesirable way. + * See the docstring at conflict_func_merge_cmd() for details */ + if (opt_state->accept_which != svn_cl__accept_unspecified) + { + struct conflict_func_merge_cmd_baton *b = apr_pcalloc(pool, sizeof(*b)); + + b->accept_which = opt_state->accept_which; + SVN_ERR(svn_dirent_get_absolute(&b->path_prefix, "", pool)); + b->conflict_stats = conflict_stats; + + ctx->conflict_func2 = conflict_func_merge_cmd; + ctx->conflict_baton2 = b; + } + merge_err = run_merge(two_sources_specified, sourcepath1, peg_revision1, sourcepath2, @@ -442,6 +543,13 @@ svn_cl__merge(apr_getopt_t *os, "fix invalid mergeinfo in target with 'svn propset'")); } + /* Run the interactive resolver if conflicts were raised. */ + SVN_ERR(svn_cl__conflict_stats_get_paths(&conflicted_paths, conflict_stats, + pool, pool)); + if (conflicted_paths) + SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats, FALSE, + opt_state, ctx, pool)); + if (!opt_state->quiet) { svn_error_t *err = svn_cl__notifier_print_conflict_stats( Modified: subversion/branches/ra-git/subversion/svn/notify.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/notify.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/notify.c (original) +++ subversion/branches/ra-git/subversion/svn/notify.c Tue Oct 11 09:11:50 2016 @@ -39,6 +39,7 @@ #include "svn_hash.h" #include "cl.h" #include "private/svn_subr_private.h" +#include "private/svn_sorts_private.h" #include "private/svn_dep_compat.h" #include "svn_private_config.h" @@ -145,6 +146,76 @@ resolved_str(apr_pool_t *pool, int n_res } svn_error_t * +svn_cl__conflict_stats_get_paths(apr_array_header_t **conflicted_paths, + svn_cl__conflict_stats_t *conflict_stats, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + + int n_text = apr_hash_count(conflict_stats->text_conflicts); + int n_prop = apr_hash_count(conflict_stats->prop_conflicts); + int n_tree = apr_hash_count(conflict_stats->tree_conflicts); + apr_hash_t *all_conflicts; + + *conflicted_paths = NULL; + if (n_text == 0 && n_prop == 0 && n_tree == 0) + return SVN_NO_ERROR; + + /* Use a hash table to ensure paths with multiple conflicts are + * returned just once. */ + all_conflicts = apr_hash_make(result_pool); + if (n_text > 0) + { + apr_array_header_t *k_text; + int i; + + SVN_ERR(svn_hash_keys(&k_text, conflict_stats->text_conflicts, + scratch_pool)); + for (i = 0; i < k_text->nelts; i++) + { + const char *path = APR_ARRAY_IDX(k_text, i, const char *); + + svn_hash_sets(all_conflicts, path, ""); + } + } + + if (n_prop > 0) + { + apr_array_header_t *k_prop; + int i; + + SVN_ERR(svn_hash_keys(&k_prop, conflict_stats->prop_conflicts, + scratch_pool)); + for (i = 0; i < k_prop->nelts; i++) + { + const char *path = APR_ARRAY_IDX(k_prop, i, const char *); + + svn_hash_sets(all_conflicts, path, ""); + } + } + + if (n_tree > 0) + { + apr_array_header_t *k_tree; + int i; + + SVN_ERR(svn_hash_keys(&k_tree, conflict_stats->tree_conflicts, + scratch_pool)); + for (i = 0; i < k_tree->nelts; i++) + { + const char *path = APR_ARRAY_IDX(k_tree, i, const char *); + + svn_hash_sets(all_conflicts, path, ""); + } + } + + svn_hash_keys(conflicted_paths, all_conflicts, result_pool); + svn_sort__array(*conflicted_paths, svn_sort_compare_paths); + + return SVN_NO_ERROR; +} + +svn_error_t * svn_cl__print_conflict_stats(svn_cl__conflict_stats_t *conflict_stats, apr_pool_t *scratch_pool) { @@ -379,6 +450,43 @@ notify_body(struct notify_baton *nb, path_local)); break; + case svn_wc_notify_resolved_text: + SVN_ERR(svn_cmdline_printf(pool, + _("Merge conflicts in '%s' marked as " + "resolved.\n"), + path_local)); + break; + + case svn_wc_notify_resolved_prop: + SVN_ERR_ASSERT(n->prop_name && strlen(n->prop_name) > 0); + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict in property '%s' at '%s' marked " + "as resolved.\n"), + n->prop_name, path_local)); + break; + + case svn_wc_notify_resolved_tree: + SVN_ERR(svn_cmdline_printf(pool, + _("Tree conflict at '%s' marked as " + "resolved.\n"), + path_local)); + break; + + case svn_wc_notify_begin_search_tree_conflict_details: + SVN_ERR(svn_cmdline_printf(pool, + _("Searching tree conflict details for '%s' " + "in repository:\n"), + path_local)); + break; + + case svn_wc_notify_tree_conflict_details_progress: + SVN_ERR(svn_cmdline_printf(pool, _("\rChecking r%ld..."), n->revision)); + break; + + case svn_wc_notify_end_search_tree_conflict_details: + SVN_ERR(svn_cmdline_printf(pool, _(" done\n"))); + break; + case svn_wc_notify_add: /* We *should* only get the MIME_TYPE if PATH is a file. If we do get it, and the mime-type is not textual, note that this Modified: subversion/branches/ra-git/subversion/svn/resolve-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/resolve-cmd.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/resolve-cmd.c (original) +++ subversion/branches/ra-git/subversion/svn/resolve-cmd.c Tue Oct 11 09:11:50 2016 @@ -88,6 +88,35 @@ tree_conflict_collector(void *baton, } } +/* + * Record a tree conflict resolution failure due to error condition ERR + * in the RESOLVE_LATER hash table. If the hash table is not available + * (meaning the caller does not wish to retry resolution later), or if + * the error condition does not indicate circumstances where another + * existing tree conflict is blocking the resolution attempt, then + * return the error ERR itself. + */ +static svn_error_t * +handle_tree_conflict_resolution_failure(const char *local_abspath, + svn_error_t *err, + apr_hash_t *resolve_later) +{ + const char *dup_abspath; + + if (!resolve_later + || (err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE + && err->apr_err != SVN_ERR_WC_FOUND_CONFLICT)) + return svn_error_trace(err); /* Give up. Do not retry resolution later. */ + + svn_error_clear(err); + dup_abspath = apr_pstrdup(apr_hash_pool_get(resolve_later), + local_abspath); + + svn_hash_sets(resolve_later, dup_abspath, dup_abspath); + + return SVN_NO_ERROR; /* Caller may retry after resolving other conflicts. */ +} + /* Implements svn_wc_status4_t to walk all conflicts to resolve. */ static svn_error_t * @@ -100,6 +129,8 @@ conflict_status_walker(void *baton, apr_pool_t *iterpool; svn_boolean_t resolved = FALSE; svn_client_conflict_t *conflict; + svn_error_t *err; + svn_boolean_t tree_conflicted; if (!status->conflicted) return SVN_NO_ERROR; @@ -108,19 +139,35 @@ conflict_status_walker(void *baton, SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, cswb->ctx, iterpool, iterpool)); - SVN_ERR(svn_cl__resolve_conflict(&resolved, cswb->accept_which, - cswb->quit, cswb->external_failed, - cswb->printed_summary, - conflict, cswb->editor_cmd, - cswb->config, cswb->path_prefix, - cswb->pb, cswb->conflict_stats, - cswb->option_id, cswb->ctx, - scratch_pool)); + SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted, + conflict, iterpool, iterpool)); + err = svn_cl__resolve_conflict(&resolved, cswb->accept_which, + cswb->quit, cswb->external_failed, + cswb->printed_summary, + conflict, cswb->editor_cmd, + cswb->config, cswb->path_prefix, + cswb->pb, cswb->conflict_stats, + cswb->option_id, cswb->ctx, + scratch_pool); + if (err) + { + if (tree_conflicted) + SVN_ERR(handle_tree_conflict_resolution_failure(local_abspath, err, + cswb->resolve_later)); + + else + return svn_error_trace(err); + } + if (resolved) cswb->resolved_one = TRUE; svn_pool_destroy(iterpool); + /* If the has user decided to quit resolution, cancel the status walk. */ + if (*cswb->quit) + return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL); + return SVN_NO_ERROR; } @@ -270,17 +317,31 @@ walk_conflicts(svn_client_ctx_t *ctx, if (iterpool) svn_pool_destroy(iterpool); - if (err && err->apr_err != SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE) - err = svn_error_createf( - SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err, - _("Unable to resolve conflicts on '%s'"), - svn_dirent_local_style(local_abspath, scratch_pool)); + if (err) + { + if (err->apr_err == SVN_ERR_CANCELLED) + { + /* If QUIT is set, the user has selected the 'q' option at + * the conflict prompt and the status walk was aborted. + * This is not an error condition. */ + if (quit) + { + svn_error_clear(err); + err = SVN_NO_ERROR; + } + } + else if (err->apr_err != SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE) + err = svn_error_createf( + SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err, + _("Unable to resolve conflicts on '%s'"), + svn_dirent_local_style(local_abspath, scratch_pool)); + + SVN_ERR(err); + } ctx->notify_func2 = cswb.notify_func; ctx->notify_baton2 = cswb.notify_baton; - SVN_ERR(err); - /* ### call notify.c code */ if (ctx->notify_func2) ctx->notify_func2(ctx->notify_baton2, @@ -292,84 +353,74 @@ walk_conflicts(svn_client_ctx_t *ctx, return SVN_NO_ERROR; } -/* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * -svn_cl__resolve(apr_getopt_t *os, - void *baton, - apr_pool_t *scratch_pool) +svn_cl__walk_conflicts(apr_array_header_t *targets, + svn_cl__conflict_stats_t *conflict_stats, + svn_boolean_t is_resolve_cmd, + svn_cl__opt_state_t *opt_state, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) { - svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; - svn_cl__conflict_stats_t *conflict_stats = - ((svn_cl__cmd_baton_t *) baton)->conflict_stats; - svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; - svn_client_conflict_option_id_t option_id; - svn_error_t *err; - apr_array_header_t *targets; - const char *path_prefix; - int i; - apr_pool_t *iterpool; svn_boolean_t had_error = FALSE; svn_boolean_t quit = FALSE; svn_boolean_t external_failed = FALSE; svn_boolean_t printed_summary = FALSE; + svn_client_conflict_option_id_t option_id; svn_cmdline_prompt_baton_t *pb = apr_palloc(scratch_pool, sizeof(*pb)); + const char *path_prefix; + svn_error_t *err; + int i; + apr_pool_t *iterpool; + + SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", scratch_pool)); pb->cancel_func = ctx->cancel_func; pb->cancel_baton = ctx->cancel_baton; - option_id = svn_client_conflict_option_unspecified; - - SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", scratch_pool)); - switch (opt_state->accept_which) { case svn_cl__accept_working: - option_id = svn_wc_conflict_choose_merged; + option_id = svn_client_conflict_option_merged_text; break; case svn_cl__accept_base: - option_id = svn_wc_conflict_choose_base; + option_id = svn_client_conflict_option_base_text; break; case svn_cl__accept_theirs_conflict: - option_id = svn_wc_conflict_choose_theirs_conflict; + option_id = svn_client_conflict_option_incoming_text_where_conflicted; break; case svn_cl__accept_mine_conflict: - option_id = svn_wc_conflict_choose_mine_conflict; + option_id = svn_client_conflict_option_working_text_where_conflicted; break; case svn_cl__accept_theirs_full: - option_id = svn_wc_conflict_choose_theirs_full; + option_id = svn_client_conflict_option_incoming_text; break; case svn_cl__accept_mine_full: - option_id = svn_wc_conflict_choose_mine_full; + option_id = svn_client_conflict_option_working_text; break; case svn_cl__accept_unspecified: - if (opt_state->non_interactive) + if (is_resolve_cmd && opt_state->non_interactive) return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("missing --accept option")); - option_id = svn_wc_conflict_choose_unspecified; + option_id = svn_client_conflict_option_unspecified; + break; + case svn_cl__accept_postpone: + if (is_resolve_cmd) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("invalid 'accept' ARG")); + option_id = svn_client_conflict_option_postpone; + break; + case svn_cl__accept_edit: + case svn_cl__accept_launch: + if (is_resolve_cmd) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("invalid 'accept' ARG")); + option_id = svn_client_conflict_option_unspecified; break; default: return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("invalid 'accept' ARG")); } - SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, - opt_state->targets, - ctx, FALSE, - scratch_pool)); - if (! targets->nelts) - svn_opt_push_implicit_dot_target(targets, scratch_pool); - - if (opt_state->depth == svn_depth_unknown) - { - if (opt_state->accept_which == svn_cl__accept_unspecified) - opt_state->depth = svn_depth_infinity; - else - opt_state->depth = svn_depth_empty; - } - - SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool)); - - SVN_ERR(svn_cl__check_targets_are_local_paths(targets)); iterpool = svn_pool_create(scratch_pool); for (i = 0; i < targets->nelts; i++) @@ -411,7 +462,7 @@ svn_cl__resolve(apr_getopt_t *os, if (err) { - svn_handle_warning2(stderr, err, "svn: "); + svn_handle_warning2(stderr, svn_error_root_cause(err), "svn: "); svn_error_clear(err); had_error = TRUE; } @@ -422,6 +473,42 @@ svn_cl__resolve(apr_getopt_t *os, return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("Failure occurred resolving one or more " "conflicts")); + return SVN_NO_ERROR; +} + +/* This implements the `svn_opt_subcommand_t' interface. */ +svn_error_t * +svn_cl__resolve(apr_getopt_t *os, + void *baton, + apr_pool_t *scratch_pool) +{ + svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; + svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; + apr_array_header_t *targets; + + SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, + opt_state->targets, + ctx, FALSE, + scratch_pool)); + if (! targets->nelts) + svn_opt_push_implicit_dot_target(targets, scratch_pool); + + if (opt_state->depth == svn_depth_unknown) + { + if (opt_state->accept_which == svn_cl__accept_unspecified) + opt_state->depth = svn_depth_infinity; + else + opt_state->depth = svn_depth_empty; + } + + SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool)); + + SVN_ERR(svn_cl__check_targets_are_local_paths(targets)); + + SVN_ERR(svn_cl__walk_conflicts(targets, conflict_stats, TRUE, + opt_state, ctx, scratch_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/ra-git/subversion/svn/status.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/status.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/status.c (original) +++ subversion/branches/ra-git/subversion/svn/status.c Tue Oct 11 09:11:50 2016 @@ -282,16 +282,10 @@ print_status(const char *target_abspath, if (tree_conflicted) { - const svn_wc_conflict_description2_t *desc2; svn_client_conflict_t *tree_conflict; - SVN_ERR(svn_wc__get_tree_conflict(&desc2, ctx->wc_ctx, - local_abspath, pool, pool)); - SVN_ERR_ASSERT(desc2 != NULL); - - SVN_ERR(svn_client_conflict_from_wc_description2_t(&tree_conflict, - desc2, - pool, pool)); + SVN_ERR(svn_client_conflict_get(&tree_conflict, local_abspath, + ctx, pool, pool)); tree_status_code = 'C'; SVN_ERR(svn_cl__get_human_readable_tree_conflict_description( &desc, tree_conflict, pool)); Modified: subversion/branches/ra-git/subversion/svn/svn.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/svn.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/svn.c (original) +++ subversion/branches/ra-git/subversion/svn/svn.c Tue Oct 11 09:11:50 2016 @@ -33,7 +33,6 @@ #include <apr_strings.h> #include <apr_tables.h> #include <apr_general.h> -#include <apr_signal.h> #include "svn_cmdline.h" #include "svn_pools.h" @@ -57,6 +56,7 @@ #include "private/svn_opt_private.h" #include "private/svn_cmdline_private.h" #include "private/svn_subr_private.h" +#include "private/svn_utf_private.h" #include "svn_private_config.h" @@ -143,6 +143,7 @@ typedef enum svn_cl__longopt_t { opt_show_passwords, opt_pin_externals, opt_show_item, + opt_adds_as_modification, } svn_cl__longopt_t; @@ -449,6 +450,15 @@ const apr_getopt_option_t svn_cl__option " " " 'wc-root' root of TARGET's working copy")}, + {"adds-as-modification", opt_adds_as_modification, 0, + N_("Local additions are merged with incoming additions " + " " + "instead of causing a tree conflict. Use of this\n" + " " + "option is not recommended! Use 'svn resolve' to\n" + " " + "resolve tree conflicts instead.")}, + /* Long-opt Aliases * * These have NULL desriptions, but an option code that matches some @@ -1761,7 +1771,7 @@ const svn_opt_subcommand_desc2_t svn_cl_ " targets of this operation.\n"), {'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_force, opt_ignore_externals, opt_changelist, opt_editor_cmd, opt_accept, - opt_parents}, + opt_parents, opt_adds_as_modification}, { {opt_force, N_("handle unversioned obstructions as changes")} } }, @@ -1795,29 +1805,8 @@ check_lib_versions(void) return svn_ver_check_list2(&my_version, checklist, svn_ver_equal); } - -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - -/* Our cancellation callback. */ -svn_error_t * -svn_cl__check_cancel(void *baton) -{ - /* Cancel baton should be always NULL in command line client. */ - SVN_ERR_ASSERT(baton == NULL); - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} +/* The cancelation handler setup by the cmdline library. */ +svn_cancel_func_t svn_cl__check_cancel = NULL; /* Add a --search argument to OPT_STATE. * These options start a new search pattern group. */ @@ -1890,6 +1879,7 @@ sub_main(int *exit_code, int argc, const svn_boolean_t reading_file_from_stdin = FALSE; apr_hash_t *changelists; apr_hash_t *cfg_hash; + svn_membuf_t buf; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -1910,6 +1900,9 @@ sub_main(int *exit_code, int argc, const /* Init our changelists hash. */ changelists = apr_hash_make(pool); + /* Init the temporary buffer. */ + svn_membuf__create(&buf, 0, pool); + /* Begin processing arguments. */ opt_state.start_revision.kind = svn_opt_revision_unspecified; opt_state.end_revision.kind = svn_opt_revision_unspecified; @@ -2414,11 +2407,20 @@ sub_main(int *exit_code, int argc, const break; case opt_search: SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); - add_search_pattern_group(&opt_state, utf8_opt_arg, pool); + SVN_ERR(svn_utf__xfrm(&utf8_opt_arg, utf8_opt_arg, + strlen(utf8_opt_arg), TRUE, TRUE, &buf)); + add_search_pattern_group(&opt_state, + apr_pstrdup(pool, utf8_opt_arg), + pool); break; case opt_search_and: SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); - add_search_pattern_to_latest_group(&opt_state, utf8_opt_arg, pool); + SVN_ERR(svn_utf__xfrm(&utf8_opt_arg, utf8_opt_arg, + strlen(utf8_opt_arg), TRUE, TRUE, &buf)); + add_search_pattern_to_latest_group(&opt_state, + apr_pstrdup(pool, utf8_opt_arg), + pool); + break; case opt_remove_unversioned: opt_state.remove_unversioned = TRUE; break; @@ -2439,6 +2441,9 @@ sub_main(int *exit_code, int argc, const SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); opt_state.show_item = utf8_opt_arg; break; + case opt_adds_as_modification: + opt_state.adds_as_modification = TRUE; + break; default: /* Hmmm. Perhaps this would be a good place to squirrel away opts that commands like svn diff might need. Hmmm indeed. */ @@ -2948,30 +2953,8 @@ sub_main(int *exit_code, int argc, const } /* Set up our cancellation support. */ + svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif /* Set up Authentication stuff. */ SVN_ERR(svn_cmdline_create_auth_baton2( @@ -3035,20 +3018,12 @@ sub_main(int *exit_code, int argc, const opt_state.accept_which = svn_cl__accept_postpone; } - /* Install the default conflict handler. */ + /* We don't use legacy libsvn_wc conflict handlers by default. */ { - svn_cl__interactive_conflict_baton_t *b; - ctx->conflict_func = NULL; ctx->conflict_baton = NULL; - - ctx->conflict_func2 = svn_cl__conflict_func_interactive; - SVN_ERR(svn_cl__get_conflict_func_interactive_baton( - &b, - opt_state.accept_which, - ctx->config, opt_state.editor_cmd, conflict_stats, - ctx->cancel_func, ctx->cancel_baton, pool)); - ctx->conflict_baton2 = b; + ctx->conflict_func2 = NULL; + ctx->conflict_baton2 = NULL; } /* And now we finally run the subcommand. */ @@ -3150,5 +3125,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } Modified: subversion/branches/ra-git/subversion/svn/switch-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/switch-cmd.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/switch-cmd.c (original) +++ subversion/branches/ra-git/subversion/svn/switch-cmd.c Tue Oct 11 09:11:50 2016 @@ -96,8 +96,11 @@ svn_cl__switch(apr_getopt_t *os, svn_error_t *err = SVN_NO_ERROR; svn_error_t *externals_err = SVN_NO_ERROR; svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; apr_array_header_t *targets; + apr_array_header_t *conflicted_paths; const char *target, *switch_url; svn_opt_revision_t peg_revision; svn_depth_t depth; @@ -188,6 +191,13 @@ svn_cl__switch(apr_getopt_t *os, _("Failure occurred processing one or " "more externals definitions")); + /* Run the interactive resolver if conflicts were raised. */ + SVN_ERR(svn_cl__conflict_stats_get_paths(&conflicted_paths, conflict_stats, + scratch_pool, scratch_pool)); + if (conflicted_paths) + SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats, FALSE, + opt_state, ctx, scratch_pool)); + if (! opt_state->quiet) { err = svn_cl__notifier_print_conflict_stats(nwb.wrapped_baton, scratch_pool); Modified: subversion/branches/ra-git/subversion/svn/update-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/update-cmd.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svn/update-cmd.c (original) +++ subversion/branches/ra-git/subversion/svn/update-cmd.c Tue Oct 11 09:11:50 2016 @@ -111,12 +111,15 @@ svn_cl__update(apr_getopt_t *os, apr_pool_t *scratch_pool) { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; apr_array_header_t *targets; svn_depth_t depth; svn_boolean_t depth_is_sticky; struct svn_cl__check_externals_failed_notify_baton nwb; apr_array_header_t *result_revs; + apr_array_header_t *conflicted_paths; svn_error_t *err = SVN_NO_ERROR; svn_error_t *externals_err = SVN_NO_ERROR; @@ -167,7 +170,8 @@ svn_cl__update(apr_getopt_t *os, &(opt_state->start_revision), depth, depth_is_sticky, opt_state->ignore_externals, - opt_state->force, TRUE /* adds_as_modification */, + opt_state->force, + opt_state->adds_as_modification, opt_state->parents, ctx, scratch_pool)); @@ -177,6 +181,13 @@ svn_cl__update(apr_getopt_t *os, _("Failure occurred processing one or " "more externals definitions")); + /* Run the interactive resolver if conflicts were raised. */ + SVN_ERR(svn_cl__conflict_stats_get_paths(&conflicted_paths, conflict_stats, + scratch_pool, scratch_pool)); + if (conflicted_paths) + SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats, FALSE, + opt_state, ctx, scratch_pool)); + if (! opt_state->quiet) { err = print_update_summary(targets, result_revs, scratch_pool); Modified: subversion/branches/ra-git/subversion/svnadmin/svnadmin.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnadmin/svnadmin.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnadmin/svnadmin.c (original) +++ subversion/branches/ra-git/subversion/svnadmin/svnadmin.c Tue Oct 11 09:11:50 2016 @@ -23,7 +23,6 @@ #include <apr_file_io.h> -#include <apr_signal.h> #include "svn_hash.h" #include "svn_pools.h" @@ -48,6 +47,7 @@ #include "private/svn_opt_private.h" #include "private/svn_sorts_private.h" #include "private/svn_subr_private.h" +#include "private/svn_cmdline_private.h" #include "svn_private_config.h" @@ -59,46 +59,7 @@ * The current threshold is 64MB. */ #define BLOCK_READ_CACHE_THRESHOLD (0x40 * 0x100000) -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - - -/* A helper to set up the cancellation signal handlers. */ -static void -setup_cancellation_signals(void (*handler)(int signum)) -{ - apr_signal(SIGINT, handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, handler); -#endif -} - - -/* Our cancellation callback. */ -static svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +static svn_cancel_func_t check_cancel = NULL; /* Custom filesystem warning function. */ static void @@ -111,34 +72,6 @@ warning_func(void *baton, } -/* Helper to open a repository and set a warning func (so we don't - * SEGFAULT when libsvn_fs's default handler gets run). */ -static svn_error_t * -open_repos(svn_repos_t **repos, - const char *path, - apr_pool_t *pool) -{ - /* Enable the "block-read" feature (where it applies)? */ - svn_boolean_t use_block_read - = svn_cache_config_get()->cache_size > BLOCK_READ_CACHE_THRESHOLD; - - /* construct FS configuration parameters: enable caches for r/o data */ - apr_hash_t *fs_config = apr_hash_make(pool); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS, "1"); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS, "1"); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, "2"); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NS, - svn_uuid_generate(pool)); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ, - use_block_read ? "1" : "0"); - - /* now, open the requested repository */ - SVN_ERR(svn_repos_open3(repos, path, fs_config, pool, pool)); - svn_fs_set_warning_func(svn_repos_fs(*repos), warning_func, NULL); - return SVN_NO_ERROR; -} - - /* Version compatibility check */ static svn_error_t * check_lib_versions(void) @@ -216,7 +149,8 @@ enum svnadmin__cmdline_options_t svnadmin__pre_1_6_compatible, svnadmin__compatible_version, svnadmin__check_normalization, - svnadmin__metadata_only + svnadmin__metadata_only, + svnadmin__no_flush_to_disk }; /* Option codes and descriptions. @@ -335,6 +269,10 @@ static const apr_getopt_option_t options " checking against external corruption in\n" " Subversion 1.9+ format repositories.\n")}, + {"no-flush-to-disk", svnadmin__no_flush_to_disk, 0, + N_("disable flushing to disk during the operation\n" + " (faster, but unsafe on power off)")}, + {NULL} }; @@ -392,7 +330,8 @@ static const svn_opt_subcommand_desc2_t "every path present in the repository as of that revision. (In either\n" "case, the second and subsequent revisions, if any, describe only paths\n" "changed in those revisions.)\n"), - {'r', svnadmin__incremental, svnadmin__deltas, 'q', 'M'} }, + {'r', svnadmin__incremental, svnadmin__deltas, 'q', 'M', 'F'}, + {{'F', N_("write to file ARG instead of stdout")}} }, {"dump-revprops", subcommand_dump_revprops, {0}, N_ ("usage: svnadmin dump-revprops REPOS_PATH [-r LOWER[:UPPER]]\n\n" @@ -401,7 +340,8 @@ static const svn_opt_subcommand_desc2_t "LOWER rev through UPPER rev. If no revisions are given, dump the\n" "properties for all revisions. If only LOWER is given, dump the\n" "properties for that one revision.\n"), - {'r', 'q'} }, + {'r', 'q', 'F'}, + {{'F', N_("write to file ARG instead of stdout")}} }, {"freeze", subcommand_freeze, {0}, N_ ("usage: 1. svnadmin freeze REPOS_PATH PROGRAM [ARG...]\n" @@ -411,7 +351,8 @@ static const svn_opt_subcommand_desc2_t "2. Like 1 except all repositories listed in FILE are locked. The file\n" " format is repository paths separated by newlines. Repositories are\n" " locked in the same order as they are listed in the file.\n"), - {'F'} }, + {'F'}, + {{'F', N_("read repository paths from file ARG")}} }, {"help", subcommand_help, {"?", "h"}, N_ ("usage: svnadmin help [SUBCOMMAND...]\n\n" @@ -453,7 +394,9 @@ static const svn_opt_subcommand_desc2_t {'q', 'r', svnadmin__ignore_uuid, svnadmin__force_uuid, svnadmin__ignore_dates, svnadmin__use_pre_commit_hook, svnadmin__use_post_commit_hook, - svnadmin__parent_dir, svnadmin__bypass_prop_validation, 'M'} }, + svnadmin__parent_dir, svnadmin__bypass_prop_validation, 'M', + svnadmin__no_flush_to_disk, 'F'}, + {{'F', N_("read from file ARG instead of stdin")}} }, {"load-revprops", subcommand_load_revprops, {0}, N_ ("usage: svnadmin load-revprops REPOS_PATH\n\n" @@ -462,7 +405,9 @@ static const svn_opt_subcommand_desc2_t "repository will cause an error. Progress feedback is sent to stdout.\n" "If --revision is specified, limit the loaded revisions to only those\n" "in the dump stream whose revision numbers match the specified range.\n"), - {'q', 'r', svnadmin__force_uuid, svnadmin__bypass_prop_validation} }, + {'q', 'r', svnadmin__force_uuid, svnadmin__bypass_prop_validation, + svnadmin__no_flush_to_disk, 'F'}, + {{'F', N_("read from file ARG instead of stdin")}} }, {"lock", subcommand_lock, {0}, N_ ("usage: svnadmin lock REPOS_PATH PATH USERNAME COMMENT-FILE [TOKEN]\n\n" @@ -599,16 +544,49 @@ struct svnadmin_opt_state svn_boolean_t metadata_only; /* --metadata-only */ svn_boolean_t bypass_prop_validation; /* --bypass-prop-validation */ svn_boolean_t ignore_dates; /* --ignore-dates */ + svn_boolean_t no_flush_to_disk; /* --no-flush-to-disk */ enum svn_repos_load_uuid uuid_action; /* --ignore-uuid, --force-uuid */ apr_uint64_t memory_cache_size; /* --memory-cache-size M */ const char *parent_dir; /* --parent-dir */ - svn_stringbuf_t *filedata; /* --file */ + const char *file; /* --file */ const char *config_dir; /* Overriding Configuration Directory */ }; +/* Helper to open a repository and set a warning func (so we don't + * SEGFAULT when libsvn_fs's default handler gets run). */ +static svn_error_t * +open_repos(svn_repos_t **repos, + const char *path, + struct svnadmin_opt_state *opt_state, + apr_pool_t *pool) +{ + /* Enable the "block-read" feature (where it applies)? */ + svn_boolean_t use_block_read + = svn_cache_config_get()->cache_size > BLOCK_READ_CACHE_THRESHOLD; + + /* construct FS configuration parameters: enable caches for r/o data */ + apr_hash_t *fs_config = apr_hash_make(pool); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS, "1"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS, "1"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS, "1"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, "2"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NS, + svn_uuid_generate(pool)); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ, + use_block_read ? "1" : "0"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_NO_FLUSH_TO_DISK, + opt_state->no_flush_to_disk ? "1" : "0"); + + /* now, open the requested repository */ + SVN_ERR(svn_repos_open3(repos, path, fs_config, pool, pool)); + svn_fs_set_warning_func(svn_repos_fs(*repos), warning_func, NULL); + return SVN_NO_ERROR; +} + + /* Set *REVNUM to the revision specified by REVISION (or to SVN_INVALID_REVNUM if that has the type 'unspecified'), possibly making use of the YOUNGEST revision number in REPOS. */ @@ -715,7 +693,7 @@ subcommand_crashtest(apr_getopt_t *os, v svn_repos_t *repos; (void)svn_error_set_malfunction_handler(crashtest_malfunction_handler); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); SVN_ERR(svn_cmdline_printf(pool, _("Successfully opened repository '%s'.\n" "Will now crash to simulate a crashing " @@ -832,7 +810,7 @@ subcommand_deltify(apr_getopt_t *os, voi /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); @@ -1089,8 +1067,7 @@ repos_notify_handler(void *baton, return; case svn_repos_notify_mutex_acquired: - /* Enable cancellation signal handlers. */ - setup_cancellation_signals(signal_handler); + svn_cmdline__setup_cancellation_handler(); return; case svn_repos_notify_recover_start: @@ -1262,23 +1239,35 @@ subcommand_dump(apr_getopt_t *os, void * { struct svnadmin_opt_state *opt_state = baton; svn_repos_t *repos; - svn_stream_t *stdout_stream; + svn_stream_t *out_stream; svn_revnum_t lower, upper; svn_stream_t *feedback_stream = NULL; /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); SVN_ERR(get_dump_range(&lower, &upper, repos, opt_state, pool)); - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); + /* Open the file or STDOUT, depending on whether -F was specified. */ + if (opt_state->file) + { + apr_file_t *file; + + /* Overwrite existing files, same as with > redirection. */ + SVN_ERR(svn_io_file_open(&file, opt_state->file, + APR_WRITE | APR_CREATE | APR_TRUNCATE + | APR_BUFFERED, APR_OS_DEFAULT, pool)); + out_stream = svn_stream_from_aprfile2(file, FALSE, pool); + } + else + SVN_ERR(svn_stream_for_stdout(&out_stream, pool)); /* Progress feedback goes to STDERR, unless they asked to suppress it. */ if (! opt_state->quiet) feedback_stream = recode_stream_create(stderr, pool); - SVN_ERR(svn_repos_dump_fs4(repos, stdout_stream, lower, upper, + SVN_ERR(svn_repos_dump_fs4(repos, out_stream, lower, upper, opt_state->incremental, opt_state->use_deltas, TRUE, TRUE, !opt_state->quiet ? repos_notify_handler : NULL, @@ -1293,23 +1282,35 @@ subcommand_dump_revprops(apr_getopt_t *o { struct svnadmin_opt_state *opt_state = baton; svn_repos_t *repos; - svn_stream_t *stdout_stream; + svn_stream_t *out_stream; svn_revnum_t lower, upper; svn_stream_t *feedback_stream = NULL; /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); SVN_ERR(get_dump_range(&lower, &upper, repos, opt_state, pool)); - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); + /* Open the file or STDOUT, depending on whether -F was specified. */ + if (opt_state->file) + { + apr_file_t *file; + + /* Overwrite existing files, same as with > redirection. */ + SVN_ERR(svn_io_file_open(&file, opt_state->file, + APR_WRITE | APR_CREATE | APR_TRUNCATE + | APR_BUFFERED, APR_OS_DEFAULT, pool)); + out_stream = svn_stream_from_aprfile2(file, FALSE, pool); + } + else + SVN_ERR(svn_stream_for_stdout(&out_stream, pool)); /* Progress feedback goes to STDERR, unless they asked to suppress it. */ if (! opt_state->quiet) feedback_stream = recode_stream_create(stderr, pool); - SVN_ERR(svn_repos_dump_fs4(repos, stdout_stream, lower, upper, + SVN_ERR(svn_repos_dump_fs4(repos, out_stream, lower, upper, FALSE, FALSE, TRUE, FALSE, !opt_state->quiet ? repos_notify_handler : NULL, feedback_stream, check_cancel, NULL, pool)); @@ -1364,7 +1365,7 @@ subcommand_freeze(apr_getopt_t *os, void return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, _("No program provided")); - if (!opt_state->filedata) + if (!opt_state->file) { /* One repository on the command line. */ paths = apr_array_make(pool, 1, sizeof(const char *)); @@ -1372,9 +1373,11 @@ subcommand_freeze(apr_getopt_t *os, void } else { + svn_stringbuf_t *buf; const char *utf8; - /* All repositories in filedata. */ - SVN_ERR(svn_utf_cstring_to_utf8(&utf8, opt_state->filedata->data, pool)); + /* Read repository paths from the -F file. */ + SVN_ERR(svn_stringbuf_from_file2(&buf, opt_state->file, pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&utf8, buf->data, pool)); paths = svn_cstring_split(utf8, "\r\n", FALSE, pool); } @@ -1493,7 +1496,7 @@ subcommand_load(apr_getopt_t *os, void * struct svnadmin_opt_state *opt_state = baton; svn_repos_t *repos; svn_revnum_t lower, upper; - svn_stream_t *stdin_stream; + svn_stream_t *in_stream; svn_stream_t *feedback_stream = NULL; /* Expect no more arguments. */ @@ -1503,16 +1506,20 @@ subcommand_load(apr_getopt_t *os, void * support a limited set of revision kinds: number and unspecified. */ SVN_ERR(get_load_range(&lower, &upper, opt_state)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); - /* Read the stream from STDIN. Users can redirect a file. */ - SVN_ERR(svn_stream_for_stdin2(&stdin_stream, TRUE, pool)); + /* Open the file or STDIN, depending on whether -F was specified. */ + if (opt_state->file) + SVN_ERR(svn_stream_open_readonly(&in_stream, opt_state->file, + pool, pool)); + else + SVN_ERR(svn_stream_for_stdin2(&in_stream, TRUE, pool)); /* Progress feedback goes to STDOUT, unless they asked to suppress it. */ if (! opt_state->quiet) feedback_stream = recode_stream_create(stdout, pool); - err = svn_repos_load_fs5(repos, stdin_stream, lower, upper, + err = svn_repos_load_fs5(repos, in_stream, lower, upper, opt_state->uuid_action, opt_state->parent_dir, opt_state->use_pre_commit_hook, opt_state->use_post_commit_hook, @@ -1536,7 +1543,7 @@ subcommand_load_revprops(apr_getopt_t *o struct svnadmin_opt_state *opt_state = baton; svn_repos_t *repos; svn_revnum_t lower, upper; - svn_stream_t *stdin_stream; + svn_stream_t *in_stream; svn_stream_t *feedback_stream = NULL; @@ -1547,16 +1554,20 @@ subcommand_load_revprops(apr_getopt_t *o support a limited set of revision kinds: number and unspecified. */ SVN_ERR(get_load_range(&lower, &upper, opt_state)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); - /* Read the stream from STDIN. Users can redirect a file. */ - SVN_ERR(svn_stream_for_stdin2(&stdin_stream, TRUE, pool)); + /* Open the file or STDIN, depending on whether -F was specified. */ + if (opt_state->file) + SVN_ERR(svn_stream_open_readonly(&in_stream, opt_state->file, + pool, pool)); + else + SVN_ERR(svn_stream_for_stdin2(&in_stream, TRUE, pool)); /* Progress feedback goes to STDOUT, unless they asked to suppress it. */ if (! opt_state->quiet) feedback_stream = recode_stream_create(stdout, pool); - err = svn_repos_load_fs_revprops(repos, stdin_stream, lower, upper, + err = svn_repos_load_fs_revprops(repos, in_stream, lower, upper, !opt_state->bypass_prop_validation, opt_state->ignore_dates, opt_state->quiet ? NULL @@ -1589,7 +1600,7 @@ subcommand_lstxns(apr_getopt_t *os, void return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Revision range is not allowed")); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_list_transactions(&txns, fs, pool)); @@ -1642,7 +1653,7 @@ subcommand_recover(apr_getopt_t *os, voi /* Restore default signal handlers until after we have acquired the * exclusive lock so that the user interrupt before we actually * touch the repository. */ - setup_cancellation_signals(SIG_DFL); + svn_cmdline__disable_cancellation_handler(); err = svn_repos_recover4(opt_state->repository_path, TRUE, repos_notify_handler, feedback_stream, @@ -1672,7 +1683,7 @@ subcommand_recover(apr_getopt_t *os, voi /* Since db transactions may have been replayed, it's nice to tell people what the latest revision is. It also proves that the recovery actually worked. */ - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); SVN_ERR(svn_fs_youngest_rev(&youngest_rev, svn_repos_fs(repos), pool)); SVN_ERR(svn_cmdline_printf(pool, _("The latest repos revision is %ld.\n"), youngest_rev)); @@ -1750,7 +1761,7 @@ subcommand_rmtxns(apr_getopt_t *os, void SVN_ERR(svn_opt_parse_all_args(&args, os, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); /* All the rest of the arguments are transaction names. */ @@ -1830,7 +1841,7 @@ set_revprop(const char *prop_name, const } /* Open the filesystem */ - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); if (opt_state->txn_id) { @@ -1906,7 +1917,7 @@ subcommand_setuuid(apr_getopt_t *os, voi if (args->nelts == 1) uuid = APR_ARRAY_IDX(args, 0, const char *); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); return svn_fs_set_uuid(fs, uuid, pool); } @@ -1954,7 +1965,7 @@ subcommand_pack(apr_getopt_t *os, void * /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); /* Progress feedback goes to STDOUT, unless they asked to suppress it. */ if (! opt_state->quiet) @@ -1989,7 +2000,7 @@ subcommand_verify(apr_getopt_t *os, void "are mutually exclusive")); } - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); @@ -2145,7 +2156,7 @@ subcommand_info(apr_getopt_t *os, void * /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_cmdline_printf(pool, _("Path: %s\n"), svn_dirent_local_style(svn_repos_path(repos, pool), @@ -2210,8 +2221,6 @@ subcommand_info(apr_getopt_t *os, void * if (!strcmp(info->fs_type, SVN_FS_TYPE_FSFS)) { const svn_fs_fsfs_info_t *fsfs_info = (const void *)info; - svn_revnum_t youngest; - SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); if (fsfs_info->shard_size) SVN_ERR(svn_cmdline_printf(pool, _("FSFS Sharded: yes\n"))); @@ -2227,7 +2236,7 @@ subcommand_info(apr_getopt_t *os, void * { const int shard_size = fsfs_info->shard_size; const long shards_packed = fsfs_info->min_unpacked_rev / shard_size; - const long shards_full = (youngest + 1) / shard_size; + const long shards_full = (head_rev + 1) / shard_size; SVN_ERR(svn_cmdline_printf(pool, _("FSFS Shards Packed: %ld/%ld\n"), shards_packed, shards_full)); } @@ -2237,6 +2246,19 @@ subcommand_info(apr_getopt_t *os, void * else SVN_ERR(svn_cmdline_printf(pool, _("FSFS Logical Addressing: no\n"))); } + else if (!strcmp(info->fs_type, SVN_FS_TYPE_FSX)) + { + const svn_fs_fsx_info_t *fsx_info = (const void *)info; + + const int shard_size = fsx_info->shard_size; + const long shards_packed = fsx_info->min_unpacked_rev / shard_size; + long shards_full = (head_rev + 1) / shard_size; + + SVN_ERR(svn_cmdline_printf(pool, _("FSX Shard Size: %d\n"), + shard_size)); + SVN_ERR(svn_cmdline_printf(pool, _("FSX Shards Packed: %ld/%ld\n"), + shards_packed, shards_full)); + } } { @@ -2287,7 +2309,7 @@ subcommand_lock(apr_getopt_t *os, void * SVN_ERR(target_arg_to_dirent(&comment_file_name, comment_file_name, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); /* Create an access context describing the user. */ @@ -2343,7 +2365,7 @@ subcommand_lslocks(apr_getopt_t *os, voi if (targets->nelts) fs_path = APR_ARRAY_IDX(targets, 0, const char *); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); /* Fetch all locks on or below the root directory. */ SVN_ERR(svn_repos_fs_get_locks2(&locks, repos, fs_path, svn_depth_infinity, @@ -2401,7 +2423,7 @@ subcommand_rmlocks(apr_getopt_t *os, voi const char *username; apr_pool_t *subpool = svn_pool_create(pool); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); /* svn_fs_unlock() demands that some username be associated with the @@ -2492,7 +2514,7 @@ subcommand_unlock(apr_getopt_t *os, void /* Open the repos/FS, and associate an access context containing USERNAME. */ - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_create_access(&access, username, pool)); SVN_ERR(svn_fs_set_access(fs, access)); @@ -2525,7 +2547,7 @@ subcommand_upgrade(apr_getopt_t *os, voi SVN_ERR(svn_stream_for_stdout(&feedback_stream, pool)); /* Restore default signal handlers. */ - setup_cancellation_signals(SIG_DFL); + svn_cmdline__disable_cancellation_handler(); err = svn_repos_upgrade2(opt_state->repository_path, TRUE, repos_notify_handler, feedback_stream, pool); @@ -2710,9 +2732,7 @@ sub_main(int *exit_code, int argc, const = 0x100000 * apr_strtoi64(opt_arg, NULL, 0); break; case 'F': - SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); - SVN_ERR(svn_stringbuf_from_file2(&(opt_state.filedata), - utf8_opt_arg, pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&(opt_state.file), opt_arg, pool)); dash_F_arg = TRUE; break; case svnadmin__version: @@ -2837,6 +2857,9 @@ sub_main(int *exit_code, int argc, const case svnadmin__wait: opt_state.wait = TRUE; break; + case svnadmin__no_flush_to_disk: + opt_state.no_flush_to_disk = TRUE; + break; default: { SVN_ERR(subcommand_help(NULL, NULL, pool)); @@ -2956,20 +2979,7 @@ sub_main(int *exit_code, int argc, const } } - /* Set up our cancellation support. */ - setup_cancellation_signals(signal_handler); - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); /* Configure FSFS caches for maximum efficiency with svnadmin. * Also, apply the respective command line parameters, if given. */ @@ -3029,5 +3039,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } Modified: subversion/branches/ra-git/subversion/svnbench/cl.h URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnbench/cl.h?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnbench/cl.h (original) +++ subversion/branches/ra-git/subversion/svnbench/cl.h Tue Oct 11 09:11:50 2016 @@ -150,8 +150,7 @@ svn_cl__try(svn_error_t *err, /* Our cancellation callback. */ -svn_error_t * -svn_cl__check_cancel(void *baton); +extern svn_cancel_func_t svn_cl__check_cancel; Modified: subversion/branches/ra-git/subversion/svnbench/svnbench.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnbench/svnbench.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnbench/svnbench.c (original) +++ subversion/branches/ra-git/subversion/svnbench/svnbench.c Tue Oct 11 09:11:50 2016 @@ -30,8 +30,6 @@ #include <string.h> #include <assert.h> -#include <apr_signal.h> - #include "svn_cmdline.h" #include "svn_dirent_uri.h" #include "svn_pools.h" @@ -327,17 +325,6 @@ check_lib_versions(void) } -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - /* Baton for ra_progress_func() callback. */ typedef struct ra_progress_baton_t { @@ -356,14 +343,7 @@ ra_progress_func(apr_off_t progress, } /* Our cancellation callback. */ -svn_error_t * -svn_cl__check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} +svn_cancel_func_t svn_cl__check_cancel = NULL; /*** Main. ***/ @@ -906,30 +886,8 @@ sub_main(int *exit_code, int argc, const } /* Set up our cancellation support. */ + svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif /* Set up Authentication stuff. */ SVN_ERR(svn_cmdline_create_auth_baton2( @@ -1047,5 +1005,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } Modified: subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.c (original) +++ subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.c Tue Oct 11 09:11:50 2016 @@ -21,8 +21,6 @@ * ==================================================================== */ -#include <apr_signal.h> - #include "svn_pools.h" #include "svn_cmdline.h" #include "svn_opt.h" @@ -42,45 +40,7 @@ /*** Code. ***/ -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - - -/* A helper to set up the cancellation signal handlers. */ -static void -setup_cancellation_signals(void (*handler)(int signum)) -{ - apr_signal(SIGINT, handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, handler); -#endif -} - - -svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +svn_cancel_func_t check_cancel = NULL; /* Custom filesystem warning function. */ static void @@ -465,19 +425,7 @@ sub_main(int *exit_code, int argc, const } /* Set up our cancellation support. */ - setup_cancellation_signals(signal_handler); - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); /* Configure FSFS caches for maximum efficiency with svnfsfs. * Also, apply the respective command line parameters, if given. */ @@ -537,5 +485,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } Modified: subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.h URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.h?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.h (original) +++ subversion/branches/ra-git/subversion/svnfsfs/svnfsfs.h Tue Oct 11 09:11:50 2016 @@ -63,8 +63,7 @@ open_fs(svn_fs_t **fs, apr_pool_t *pool); /* Our cancellation callback. */ -svn_error_t * -check_cancel(void *baton); +extern svn_cancel_func_t check_cancel; #ifdef __cplusplus } Modified: subversion/branches/ra-git/subversion/svnlook/svnlook.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnlook/svnlook.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnlook/svnlook.c (original) +++ subversion/branches/ra-git/subversion/svnlook/svnlook.c Tue Oct 11 09:11:50 2016 @@ -28,7 +28,6 @@ #include <apr_pools.h> #include <apr_time.h> #include <apr_file_io.h> -#include <apr_signal.h> #define APR_WANT_STDIO #define APR_WANT_STRFUNC @@ -374,30 +373,10 @@ typedef struct svnlook_ctxt_t } svnlook_ctxt_t; -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - /*** Helper functions. ***/ -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - -/* Our cancellation callback. */ -static svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +static svn_cancel_func_t check_cancel = NULL; /* Version compatibility check */ static svn_error_t * @@ -2800,30 +2779,7 @@ sub_main(int *exit_code, int argc, const } } - /* Set up our cancellation support. */ - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); /* Configure FSFS caches for maximum efficiency with svnadmin. * Also, apply the respective command line parameters, if given. */ @@ -2883,5 +2839,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } Modified: subversion/branches/ra-git/subversion/svnmucc/svnmucc.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnmucc/svnmucc.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnmucc/svnmucc.c (original) +++ subversion/branches/ra-git/subversion/svnmucc/svnmucc.c Tue Oct 11 09:11:50 2016 @@ -74,6 +74,7 @@ check_lib_versions(void) return svn_ver_check_list2(&my_version, checklist, svn_ver_equal); } +/* Implements svn_commit_callback2_t */ static svn_error_t * commit_callback(const svn_commit_info_t *commit_info, void *baton, @@ -84,6 +85,15 @@ commit_callback(const svn_commit_info_t (commit_info->author ? commit_info->author : "(no author)"), commit_info->date)); + + /* Writing to stdout, as there maybe systems that consider the + * presence of stderr as an indication of commit failure. + * OTOH, this is only of informational nature to the user as + * the commit has succeeded. */ + if (commit_info->post_commit_err) + SVN_ERR(svn_cmdline_printf(pool, _("\nWarning: %s\n"), + commit_info->post_commit_err)); + return SVN_NO_ERROR; } Modified: subversion/branches/ra-git/subversion/svnrdump/svnrdump.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnrdump/svnrdump.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/svnrdump/svnrdump.c (original) +++ subversion/branches/ra-git/subversion/svnrdump/svnrdump.c Tue Oct 11 09:11:50 2016 @@ -22,7 +22,6 @@ * ==================================================================== */ -#include <apr_signal.h> #include <apr_uri.h> #include "svn_pools.h" @@ -47,27 +46,8 @@ /*** Cancellation ***/ -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - /* Our cancellation callback. */ -static svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +static svn_cancel_func_t check_cancel = NULL; @@ -805,27 +785,7 @@ sub_main(int *exit_code, int argc, const os->interleave = TRUE; /* Options and arguments can be interleaved */ /* Set up our cancellation support. */ - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -1157,5 +1117,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; }