You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2016/12/13 12:36:57 UTC
svn commit: r1773992 [5/8] - in /subversion/branches/ra-git: ./
build/ac-macros/ notes/ subversion/bindings/javahl/native/
subversion/bindings/swig/perl/libsvn_swig_perl/
subversion/bindings/swig/ruby/test/ subversion/include/
subversion/include/privat...
Modified: subversion/branches/ra-git/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/conflict-callbacks.c?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/ra-git/subversion/svn/conflict-callbacks.c Tue Dec 13 12:36:55 2016
@@ -229,8 +229,8 @@ merge_prop_conflict(svn_stream_t *output
base_propval = svn_string_create_empty(pool);
if (my_propval == NULL)
my_propval = svn_string_create_empty(pool);
- if (my_propval == NULL)
- my_propval = svn_string_create_empty(pool);
+ if (their_propval == NULL)
+ their_propval = svn_string_create_empty(pool);
options->ignore_eol_style = TRUE;
SVN_ERR(svn_diff_mem_string_diff3(&diff, base_propval,
@@ -374,148 +374,140 @@ edit_prop_conflict(const svn_string_t **
typedef struct resolver_option_t
{
const char *code; /* one or two characters */
- const char *short_desc; /* label in prompt (localized) */
- const char *long_desc; /* longer description (localized) */
svn_client_conflict_option_id_t choice;
/* or ..._undefined if not from libsvn_client */
const char *accept_arg; /* --accept option argument (NOT localized) */
} resolver_option_t;
+typedef struct client_option_t
+{
+ const char *code; /* one or two characters */
+ const char *label; /* label in prompt (localized) */
+ const char *long_desc; /* longer description (localized) */
+ svn_client_conflict_option_id_t choice;
+ /* or ..._undefined if not from libsvn_client */
+ const char *accept_arg; /* --accept option argument (NOT localized) */
+} client_option_t;
+
/* Resolver options for conflict options offered by libsvn_client. */
static const resolver_option_t builtin_resolver_options[] =
{
- { "r", NULL, NULL,
- svn_client_conflict_option_merged_text,
- SVN_CL__ACCEPT_WORKING },
- { "mc", NULL, NULL,
- svn_client_conflict_option_working_text_where_conflicted,
- SVN_CL__ACCEPT_MINE_CONFLICT },
- { "tc", NULL, NULL,
- svn_client_conflict_option_incoming_text_where_conflicted,
- SVN_CL__ACCEPT_THEIRS_CONFLICT },
- { "mf", NULL, NULL,
- svn_client_conflict_option_working_text,
- SVN_CL__ACCEPT_MINE_FULL},
- { "tf", NULL, NULL,
- svn_client_conflict_option_incoming_text,
- SVN_CL__ACCEPT_THEIRS_FULL },
- { "p", N_("postpone"), NULL,
- svn_client_conflict_option_postpone,
- SVN_CL__ACCEPT_POSTPONE },
+ { "r", svn_client_conflict_option_merged_text,
+ SVN_CL__ACCEPT_WORKING },
+ { "mc", svn_client_conflict_option_working_text_where_conflicted,
+ SVN_CL__ACCEPT_MINE_CONFLICT },
+ { "tc", svn_client_conflict_option_incoming_text_where_conflicted,
+ SVN_CL__ACCEPT_THEIRS_CONFLICT },
+ { "mf", svn_client_conflict_option_working_text,
+ SVN_CL__ACCEPT_MINE_FULL},
+ { "tf", svn_client_conflict_option_incoming_text,
+ SVN_CL__ACCEPT_THEIRS_FULL },
+ { "p", svn_client_conflict_option_postpone,
+ SVN_CL__ACCEPT_POSTPONE },
/* This option resolves a tree conflict to the current working copy state. */
- { "r", NULL, NULL,
- svn_client_conflict_option_accept_current_wc_state,
- SVN_CL__ACCEPT_WORKING },
+ { "r", svn_client_conflict_option_accept_current_wc_state,
+ SVN_CL__ACCEPT_WORKING },
/* These options use the same code since they only occur in
* distinct conflict scenarios. */
- { "u", N_("update move destination"), NULL,
- svn_client_conflict_option_update_move_destination },
- { "u", N_("update any moved-away children"), NULL,
- svn_client_conflict_option_update_any_moved_away_children },
+ { "u", svn_client_conflict_option_update_move_destination },
+ { "u", svn_client_conflict_option_update_any_moved_away_children },
/* Options for incoming add vs local add. */
- { "i", N_("ignore incoming addition"), NULL,
- svn_client_conflict_option_incoming_add_ignore },
+ { "i", svn_client_conflict_option_incoming_add_ignore },
/* Options for incoming file add vs local file add upon merge. */
- { "m", N_("merge the files"), NULL,
- svn_client_conflict_option_incoming_added_file_text_merge },
- { "R", N_("delete my file and replace it with incoming file"), NULL,
- svn_client_conflict_option_incoming_added_file_replace },
- { "M", N_("replace my file with incoming file and merge the files"), NULL,
- svn_client_conflict_option_incoming_added_file_replace_and_merge },
+ { "m", svn_client_conflict_option_incoming_added_file_text_merge },
+ { "M", svn_client_conflict_option_incoming_added_file_replace_and_merge },
/* Options for incoming dir add vs local dir add upon merge. */
- { "m", N_("merge the directories"), NULL,
- svn_client_conflict_option_incoming_added_dir_merge },
- { "R", N_("delete my directory and replace it with incoming directory"), NULL,
- svn_client_conflict_option_incoming_added_dir_replace },
- { "M", N_("replace my directory with incoming directory and merge"), NULL,
- svn_client_conflict_option_incoming_added_dir_replace_and_merge },
+ { "m", svn_client_conflict_option_incoming_added_dir_merge },
+ { "R", svn_client_conflict_option_incoming_added_dir_replace },
+ { "M", svn_client_conflict_option_incoming_added_dir_replace_and_merge },
/* Options for incoming delete vs any. */
- { "i", N_("ignore incoming deletion"), NULL,
- svn_client_conflict_option_incoming_delete_ignore },
- { "a", N_("accept incoming deletion"), NULL,
- svn_client_conflict_option_incoming_delete_accept },
+ { "i", svn_client_conflict_option_incoming_delete_ignore },
+ { "a", svn_client_conflict_option_incoming_delete_accept },
/* Options for incoming move vs local edit. */
- { "m", NULL, NULL, svn_client_conflict_option_incoming_move_file_text_merge },
- { "m", NULL, NULL, svn_client_conflict_option_incoming_move_dir_merge },
+ { "m", svn_client_conflict_option_incoming_move_file_text_merge },
+ { "m", svn_client_conflict_option_incoming_move_dir_merge },
+
+ /* Options for local move vs incoming edit. */
+ { "m", svn_client_conflict_option_local_move_file_text_merge },
{ NULL }
};
/* Extra resolver options offered by 'svn' for any conflict. */
-static const resolver_option_t extra_resolver_options[] =
+static const client_option_t extra_resolver_options[] =
{
/* Translators: keep long_desc below 70 characters (wrap with a left
margin of 9 spaces if needed) */
- { "q", N_("quit resolution"), N_("postpone all remaining conflicts"),
+ { "q", N_("Quit resolution"), N_("postpone all remaining conflicts"),
svn_client_conflict_option_postpone },
{ NULL }
};
/* Additional resolver options offered by 'svn' for a text conflict. */
-static const resolver_option_t extra_resolver_options_text[] =
+static const client_option_t extra_resolver_options_text[] =
{
/* Translators: keep long_desc below 70 characters (wrap with a left
margin of 9 spaces if needed) */
- { "e", N_("edit file"), N_("change merged file in an editor"),
+ { "e", N_("Edit file"), N_("change merged file in an editor"),
svn_client_conflict_option_undefined,
SVN_CL__ACCEPT_EDIT },
- { "df", N_("show diff"), N_("show all changes made to merged file"),
+ { "df", N_("Show diff"), N_("show all changes made to merged file"),
svn_client_conflict_option_undefined},
- { "dc", N_("display conflict"), N_("show all conflicts "
+ { "dc", N_("Display conflict"), N_("show all conflicts "
"(ignoring merged version)"),
svn_client_conflict_option_undefined },
- { "m", N_("merge"), N_("use merge tool to resolve conflict"),
+ { "m", N_("Merge"), N_("use merge tool to resolve conflict"),
svn_client_conflict_option_undefined },
- { "l", N_("launch tool"), N_("launch external merge tool to resolve "
+ { "l", N_("Launch tool"), N_("launch external merge tool to resolve "
"conflict"),
svn_client_conflict_option_undefined,
SVN_CL__ACCEPT_LAUNCH },
- { "i", N_("internal merge tool"), N_("use built-in merge tool to "
+ { "i", N_("Internal merge tool"), N_("use built-in merge tool to "
"resolve conflict"),
svn_client_conflict_option_undefined },
- { "s", N_("show all options"), N_("show this list (also 'h', '?')"),
+ { "s", N_("Show all options"), N_("show this list (also 'h', '?')"),
svn_client_conflict_option_undefined },
{ NULL }
};
/* Additional resolver options offered by 'svn' for a property conflict. */
-static const resolver_option_t extra_resolver_options_prop[] =
+static const client_option_t extra_resolver_options_prop[] =
{
/* Translators: keep long_desc below 70 characters (wrap with a left
margin of 9 spaces if needed) */
- { "dc", N_("display conflict"), N_("show conflicts in this property"),
+ { "dc", N_("Display conflict"), N_("show conflicts in this property"),
svn_client_conflict_option_undefined },
- { "e", N_("edit property"), N_("change merged property value in an "
+ { "e", N_("Edit property"), N_("change merged property value in an "
"editor"),
svn_client_conflict_option_undefined,
SVN_CL__ACCEPT_EDIT },
- { "h", N_("help"), N_("show this help (also '?')"),
+ { "h", N_("Help"), N_("show this help (also '?')"),
svn_client_conflict_option_undefined },
{ NULL }
};
/* Additional resolver options offered by 'svn' for a tree conflict. */
-static const resolver_option_t extra_resolver_options_tree[] =
+static const client_option_t extra_resolver_options_tree[] =
{
/* Translators: keep long_desc below 70 characters (wrap with a left
margin of 9 spaces if needed) */
- { "d", N_("set repository move destination path"),
+ { "d", N_("Set repository move destination path"),
N_("pick repository move target from list of possible targets"),
svn_client_conflict_option_undefined },
- { "w", N_("set working copy move destination path"),
+ { "w", N_("Set working copy move destination path"),
N_("pick working copy move target from list of possible targets"),
svn_client_conflict_option_undefined },
- { "h", N_("help"), N_("show this help (also '?')"),
+ { "h", N_("Help"), N_("show this help (also '?')"),
svn_client_conflict_option_undefined },
{ NULL }
@@ -524,14 +516,16 @@ static const resolver_option_t extra_res
/* Return a pointer to the option description in OPTIONS matching the
* one- or two-character OPTION_CODE. Return NULL if not found. */
-static const resolver_option_t *
-find_option(const resolver_option_t *options,
+static const client_option_t *
+find_option(const apr_array_header_t *options,
const char *option_code)
{
- const resolver_option_t *opt;
+ int i;
- for (opt = options; opt->code; opt++)
+ for (i = 0; i < options->nelts; i++)
{
+ const client_option_t *opt = APR_ARRAY_IDX(options, i, client_option_t *);
+
/* Ignore code "" (blank lines) which is not a valid answer. */
if (opt->code[0] && strcmp(opt->code, option_code) == 0)
return opt;
@@ -540,25 +534,52 @@ find_option(const resolver_option_t *opt
}
/* Return a pointer to the option description in OPTIONS matching the
- * the conflict option ID CHOICE. Return NULL if not found. */
-static const resolver_option_t *
-find_option_by_id(const resolver_option_t *options,
- svn_client_conflict_option_id_t choice)
+ * conflict option ID CHOICE. @a out will be set to NULL if the
+ * option was not found. */
+static svn_error_t *
+find_option_by_builtin(client_option_t **out,
+ const resolver_option_t *options,
+ svn_client_conflict_option_t *builtin_option,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
const resolver_option_t *opt;
+ svn_client_conflict_option_id_t id;
+
+ id = svn_client_conflict_option_get_id(builtin_option);
for (opt = options; opt->code; opt++)
{
- if (opt->choice == choice)
- return opt;
+ if (opt->choice == id)
+ {
+ client_option_t *client_opt;
+
+ client_opt = apr_pcalloc(result_pool, sizeof(*client_opt));
+ client_opt->choice = id;
+ client_opt->code = opt->code;
+ client_opt->label = svn_client_conflict_option_get_label(
+ builtin_option,
+ result_pool);
+ client_opt->long_desc = svn_client_conflict_option_get_description(
+ builtin_option,
+ result_pool);
+ client_opt->accept_arg = opt->accept_arg;
+
+ *out = client_opt;
+
+ return SVN_NO_ERROR;
+ }
}
- return NULL;
+
+ *out = NULL;
+
+ return SVN_NO_ERROR;
}
/* Return a prompt string listing the options OPTIONS. If OPTION_CODES is
* non-null, select only the options whose codes are mentioned in it. */
static const char *
-prompt_string(const resolver_option_t *options,
+prompt_string(const apr_array_header_t *options,
const char *const *option_codes,
apr_pool_t *pool)
{
@@ -567,10 +588,11 @@ prompt_string(const resolver_option_t *o
const char *line_sep = apr_psprintf(pool, "\n%*s", left_margin, "");
int this_line_len = left_margin;
svn_boolean_t first = TRUE;
+ int i = 0;
while (1)
{
- const resolver_option_t *opt;
+ const client_option_t *opt;
const char *s;
int slen;
@@ -584,15 +606,16 @@ prompt_string(const resolver_option_t *o
}
else
{
- opt = options++;
- if (! opt->code)
+ if (i >= options->nelts)
break;
+ opt = APR_ARRAY_IDX(options, i, client_option_t *);
+ i++;
}
if (! first)
result = apr_pstrcat(pool, result, ",", SVN_VA_NULL);
s = apr_psprintf(pool, " (%s) %s", opt->code,
- opt->short_desc ? _(opt->short_desc) : opt->long_desc);
+ opt->label ? opt->label : opt->long_desc);
slen = svn_utf_cstring_utf8_width(s);
/* Break the line if adding the next option would make it too long */
if (this_line_len + slen > MAX_PROMPT_WIDTH)
@@ -610,18 +633,22 @@ prompt_string(const resolver_option_t *o
/* Return a help string listing the OPTIONS. */
static svn_error_t *
help_string(const char **result,
- const resolver_option_t *options,
+ const apr_array_header_t *options,
apr_pool_t *pool)
{
- const resolver_option_t *opt;
apr_pool_t *iterpool;
+ int i;
*result = "";
iterpool = svn_pool_create(pool);
- for (opt = options; opt->code; opt++)
+ for (i = 0; i < options->nelts; i++)
{
+ const client_option_t *opt;
svn_pool_clear(iterpool);
+ opt = APR_ARRAY_IDX(options, i,
+ client_option_t *);
+
/* Append a line describing OPT, or a blank line if its code is "". */
if (opt->code[0])
{
@@ -658,8 +685,8 @@ help_string(const char **result,
* *OPT == NULL.
*/
static svn_error_t *
-prompt_user(const resolver_option_t **opt,
- const resolver_option_t *conflict_options,
+prompt_user(const client_option_t **opt,
+ const apr_array_header_t *conflict_options,
const char *const *options_to_show,
const char *conflict_description,
void *prompt_baton,
@@ -695,15 +722,14 @@ prompt_user(const resolver_option_t **op
/* Set *OPTIONS to an array of resolution options for CONFLICT. */
static svn_error_t *
-build_text_conflict_options(resolver_option_t **options,
+build_text_conflict_options(apr_array_header_t **options,
svn_client_conflict_t *conflict,
svn_client_ctx_t *ctx,
svn_boolean_t is_binary,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- resolver_option_t *opt;
- const resolver_option_t *o;
+ const client_option_t *o;
apr_array_header_t *builtin_options;
apr_size_t nopt;
int i;
@@ -716,41 +742,34 @@ build_text_conflict_options(resolver_opt
nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options);
if (!is_binary)
nopt += ARRAY_LEN(extra_resolver_options_text);
- *options = apr_pcalloc(result_pool, sizeof(*opt) * (nopt + 1));
+ *options = apr_array_make(result_pool, nopt, sizeof(client_option_t *));
- opt = *options;
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < builtin_options->nelts; i++)
{
+ client_option_t *opt;
svn_client_conflict_option_t *builtin_option;
- svn_client_conflict_option_id_t id;
- const resolver_option_t *known_option;
svn_pool_clear(iterpool);
builtin_option = APR_ARRAY_IDX(builtin_options, i,
svn_client_conflict_option_t *);
- id = svn_client_conflict_option_get_id(builtin_option);
- known_option = find_option_by_id(builtin_resolver_options, id);
- if (known_option == NULL)
+ SVN_ERR(find_option_by_builtin(&opt,
+ builtin_resolver_options,
+ builtin_option,
+ result_pool,
+ iterpool));
+ if (opt == NULL)
continue; /* ### unknown option -- assign a code dynamically? */
- opt->code = known_option->code;
- opt->short_desc = known_option->short_desc;
- SVN_ERR(svn_client_conflict_option_describe(&opt->long_desc,
- builtin_option,
- result_pool,
- iterpool));
- opt->choice = id;
- opt->accept_arg = known_option->accept_arg;
- opt++;
+ APR_ARRAY_PUSH(*options, client_option_t *) = opt;
}
for (o = extra_resolver_options; o->code; o++)
- *opt++ = *o;
+ APR_ARRAY_PUSH(*options, const client_option_t *) = o;
if (!is_binary)
{
for (o = extra_resolver_options_text; o->code; o++)
- *opt++ = *o;
+ APR_ARRAY_PUSH(*options, const client_option_t *) = o;
}
svn_pool_destroy(iterpool);
@@ -842,7 +861,7 @@ handle_text_conflict(svn_boolean_t *reso
const char *my_abspath;
const char *their_abspath;
const char *merged_abspath = svn_client_conflict_get_local_abspath(conflict);
- resolver_option_t *text_conflict_options;
+ apr_array_header_t *text_conflict_options;
svn_client_conflict_option_id_t option_id;
option_id = svn_client_conflict_option_unspecified;
@@ -889,8 +908,7 @@ handle_text_conflict(svn_boolean_t *reso
{
const char *suggested_options[9]; /* filled statically below */
const char **next_option = suggested_options;
- const resolver_option_t *opt;
-
+ const client_option_t *opt;
svn_pool_clear(iterpool);
@@ -915,10 +933,9 @@ handle_text_conflict(svn_boolean_t *reso
if (knows_something || is_binary)
*next_option++ = "r";
- /* The 'mine-full' option selects the ".mine" file so only offer
- * it if that file exists. It does not exist for binary files,
- * for example (questionable historical behaviour since 1.0). */
- if (my_abspath)
+ /* The 'mine-full' option selects the ".mine" file for texts or
+ * the current working directory file for binary files. */
+ if (my_abspath || is_binary)
*next_option++ = "mf";
*next_option++ = "tf";
@@ -1167,14 +1184,13 @@ handle_text_conflict(svn_boolean_t *reso
/* Set *OPTIONS to an array of resolution options for CONFLICT. */
static svn_error_t *
-build_prop_conflict_options(resolver_option_t **options,
+build_prop_conflict_options(apr_array_header_t **options,
svn_client_conflict_t *conflict,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- resolver_option_t *opt;
- const resolver_option_t *o;
+ const client_option_t *o;
apr_array_header_t *builtin_options;
apr_size_t nopt;
int i;
@@ -1186,42 +1202,34 @@ build_prop_conflict_options(resolver_opt
scratch_pool));
nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options) +
ARRAY_LEN(extra_resolver_options_prop);
- *options = apr_pcalloc(result_pool, sizeof(*opt) * (nopt + 1));
+ *options = apr_array_make(result_pool, nopt, sizeof(client_option_t *));
- opt = *options;
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < builtin_options->nelts; i++)
{
+ client_option_t *opt;
svn_client_conflict_option_t *builtin_option;
- svn_client_conflict_option_id_t id;
- const resolver_option_t *known_option;
svn_pool_clear(iterpool);
builtin_option = APR_ARRAY_IDX(builtin_options, i,
svn_client_conflict_option_t *);
- id = svn_client_conflict_option_get_id(builtin_option);
- known_option = find_option_by_id(builtin_resolver_options, id);
- if (known_option == NULL)
+ SVN_ERR(find_option_by_builtin(&opt,
+ builtin_resolver_options,
+ builtin_option,
+ result_pool,
+ iterpool));
+ if (opt == NULL)
continue; /* ### unknown option -- assign a code dynamically? */
- opt->code = known_option->code;
- opt->short_desc = known_option->short_desc;
- SVN_ERR(svn_client_conflict_option_describe(&opt->long_desc,
- builtin_option,
- result_pool,
- iterpool));
- opt->choice = id;
- opt->accept_arg = known_option->accept_arg;
-
- opt++;
+ APR_ARRAY_PUSH(*options, client_option_t *) = opt;
}
svn_pool_destroy(iterpool);
for (o = extra_resolver_options; o->code; o++)
- *opt++ = *o;
+ APR_ARRAY_PUSH(*options, const client_option_t *) = o;
for (o = extra_resolver_options_prop; o->code; o++)
- *opt++ = *o;
+ APR_ARRAY_PUSH(*options, const client_option_t *) = o;
return SVN_NO_ERROR;
}
@@ -1250,7 +1258,7 @@ handle_one_prop_conflict(svn_client_conf
const svn_string_t *my_propval;
const svn_string_t *their_propval;
apr_array_header_t *resolution_options;
- resolver_option_t *prop_conflict_options;
+ apr_array_header_t *prop_conflict_options;
SVN_ERR(svn_client_conflict_prop_get_propvals(NULL, &my_propval,
&base_propval, &their_propval,
@@ -1278,7 +1286,7 @@ handle_one_prop_conflict(svn_client_conf
iterpool = svn_pool_create(scratch_pool);
while (TRUE)
{
- const resolver_option_t *opt;
+ const client_option_t *opt;
const char *suggested_options[9]; /* filled statically below */
const char **next_option = suggested_options;
@@ -1425,57 +1433,62 @@ handle_prop_conflicts(svn_boolean_t *res
/* Set *OPTIONS to an array of resolution options for CONFLICT. */
static svn_error_t *
build_tree_conflict_options(
- resolver_option_t **options,
+ apr_array_header_t **options,
apr_array_header_t **possible_moved_to_repos_relpaths,
apr_array_header_t **possible_moved_to_abspaths,
+ svn_boolean_t *all_options_are_dumb,
svn_client_conflict_t *conflict,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- resolver_option_t *opt;
- const resolver_option_t *o;
+ const client_option_t *o;
apr_array_header_t *builtin_options;
apr_size_t nopt;
int i;
apr_pool_t *iterpool;
+ if (all_options_are_dumb != NULL)
+ *all_options_are_dumb = TRUE;
+
SVN_ERR(svn_client_conflict_tree_get_resolution_options(&builtin_options,
conflict, ctx,
scratch_pool,
scratch_pool));
nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options_tree) +
ARRAY_LEN(extra_resolver_options);
- *options = apr_pcalloc(result_pool, sizeof(*opt) * (nopt + 1));
+ *options = apr_array_make(result_pool, nopt, sizeof(client_option_t *));
*possible_moved_to_abspaths = NULL;
*possible_moved_to_repos_relpaths = NULL;
- opt = *options;
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < builtin_options->nelts; i++)
{
+ client_option_t *opt;
svn_client_conflict_option_t *builtin_option;
svn_client_conflict_option_id_t id;
- const resolver_option_t *known_option;
svn_pool_clear(iterpool);
builtin_option = APR_ARRAY_IDX(builtin_options, i,
svn_client_conflict_option_t *);
- id = svn_client_conflict_option_get_id(builtin_option);
- known_option = find_option_by_id(builtin_resolver_options, id);
- if (known_option == NULL)
+ SVN_ERR(find_option_by_builtin(&opt,
+ builtin_resolver_options,
+ builtin_option,
+ result_pool,
+ iterpool));
+ if (opt == NULL)
continue; /* ### unknown option -- assign a code dynamically? */
- opt->code = known_option->code;
- opt->short_desc = known_option->short_desc;
- SVN_ERR(svn_client_conflict_option_describe(&opt->long_desc,
- builtin_option,
- result_pool,
- iterpool));
- opt->choice = id;
- opt->accept_arg = known_option->accept_arg;
+ APR_ARRAY_PUSH(*options, client_option_t *) = opt;
- opt++;
+ id = svn_client_conflict_option_get_id(builtin_option);
+
+ /* Check if we got a "smart" tree conflict option. */
+ if (all_options_are_dumb != NULL &&
+ *all_options_are_dumb &&
+ id != svn_client_conflict_option_postpone &&
+ id != svn_client_conflict_option_accept_current_wc_state)
+ *all_options_are_dumb = FALSE;
if (id == svn_client_conflict_option_incoming_move_file_text_merge ||
id == svn_client_conflict_option_incoming_move_dir_merge)
@@ -1505,10 +1518,10 @@ build_tree_conflict_options(
(*possible_moved_to_abspaths)->nelts <= 1))
continue;
- *opt++ = *o;
+ APR_ARRAY_PUSH(*options, const client_option_t *) = o;
}
for (o = extra_resolver_options; o->code; o++)
- *opt++ = *o;
+ APR_ARRAY_PUSH(*options, const client_option_t *) = o;
return SVN_NO_ERROR;
}
@@ -1633,7 +1646,7 @@ handle_tree_conflict(svn_boolean_t *reso
apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool;
- resolver_option_t *tree_conflict_options;
+ apr_array_header_t *tree_conflict_options;
svn_client_conflict_option_id_t option_id;
const char *local_abspath;
const char *conflict_description;
@@ -1641,6 +1654,7 @@ handle_tree_conflict(svn_boolean_t *reso
const char *incoming_change_description;
apr_array_header_t *possible_moved_to_repos_relpaths;
apr_array_header_t *possible_moved_to_abspaths;
+ svn_boolean_t all_options_are_dumb;
option_id = svn_client_conflict_option_unspecified;
local_abspath = svn_client_conflict_get_local_abspath(conflict);
@@ -1664,12 +1678,20 @@ handle_tree_conflict(svn_boolean_t *reso
SVN_ERR(build_tree_conflict_options(&tree_conflict_options,
&possible_moved_to_repos_relpaths,
&possible_moved_to_abspaths,
+ &all_options_are_dumb,
conflict, ctx,
scratch_pool, scratch_pool));
+
+ if (all_options_are_dumb)
+ SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool,
+ _("\nSubversion is not smart enough to resolve "
+ "this tree conflict automatically!\nSee 'svn "
+ "help resolve' for more information.\n\n")));
+
iterpool = svn_pool_create(scratch_pool);
while (1)
{
- const resolver_option_t *opt;
+ const client_option_t *opt;
svn_pool_clear(iterpool);
@@ -1723,7 +1745,7 @@ handle_tree_conflict(svn_boolean_t *reso
&tree_conflict_options,
&possible_moved_to_repos_relpaths,
&possible_moved_to_abspaths,
- conflict, ctx,
+ NULL, conflict, ctx,
scratch_pool, scratch_pool));
}
continue;
@@ -1765,7 +1787,7 @@ handle_tree_conflict(svn_boolean_t *reso
&tree_conflict_options,
&possible_moved_to_repos_relpaths,
&possible_moved_to_abspaths,
- conflict, ctx,
+ NULL, conflict, ctx,
scratch_pool, scratch_pool));
}
continue;
@@ -1796,163 +1818,6 @@ handle_tree_conflict(svn_boolean_t *reso
}
static svn_error_t *
-resolve_conflict_by_accept_option(svn_client_conflict_option_id_t *option_id,
- svn_cl__accept_t accept_which,
- svn_boolean_t *external_failed,
- svn_client_conflict_t *conflict,
- const char *editor_cmd,
- apr_hash_t *config,
- const char *path_prefix,
- svn_cmdline_prompt_baton_t *pb,
- svn_cl__conflict_stats_t *conflict_stats,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_error_t *err;
- const char *base_abspath = NULL;
- const char *my_abspath = NULL;
- const char *their_abspath = NULL;
- const char *merged_abspath = svn_client_conflict_get_local_abspath(conflict);
- svn_boolean_t text_conflicted;
- apr_array_header_t *props_conflicted;
- svn_boolean_t tree_conflicted;
-
- SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
- &props_conflicted,
- &tree_conflicted,
- conflict,
- scratch_pool,
- scratch_pool));
-
- if (text_conflicted)
- SVN_ERR(svn_client_conflict_text_get_contents(NULL, &my_abspath,
- &base_abspath,
- &their_abspath,
- conflict, scratch_pool,
- scratch_pool));
-
- *option_id = svn_client_conflict_option_unspecified;
- /* Handle the --accept option. */
- switch (accept_which)
- {
- case svn_cl__accept_invalid:
- case svn_cl__accept_unspecified:
- /* No (or no valid) --accept option, fall through to prompting. */
- break;
- case svn_cl__accept_postpone:
- *option_id = svn_client_conflict_option_postpone;
- break;
- case svn_cl__accept_base:
- *option_id = svn_client_conflict_option_base_text;
- break;
- case svn_cl__accept_working:
- *option_id = svn_client_conflict_option_merged_text;
- break;
- case svn_cl__accept_mine_conflict:
- *option_id = svn_client_conflict_option_working_text_where_conflicted;
- break;
- case svn_cl__accept_theirs_conflict:
- *option_id = svn_client_conflict_option_incoming_text_where_conflicted;
- break;
- case svn_cl__accept_mine_full:
- *option_id = svn_client_conflict_option_working_text;
- break;
- case svn_cl__accept_theirs_full:
- *option_id = svn_client_conflict_option_incoming_text;
- break;
- case svn_cl__accept_edit:
- if (merged_abspath)
- {
- if (*external_failed)
- {
- *option_id = svn_client_conflict_option_postpone;
- break;
- }
-
- err = svn_cmdline__edit_file_externally(merged_abspath,
- editor_cmd, config,
- scratch_pool);
- if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR ||
- err->apr_err == SVN_ERR_EXTERNAL_PROGRAM))
- {
- char buf[1024];
- const char *message;
-
- message = svn_err_best_message(err, buf, sizeof(buf));
- SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
- message));
- svn_error_clear(err);
- *external_failed = TRUE;
- }
- else if (err)
- return svn_error_trace(err);
- *option_id = svn_client_conflict_option_merged_text;
- break;
- }
- /* else, fall through to prompting. */
- break;
- case svn_cl__accept_launch:
- if (base_abspath && their_abspath && my_abspath && merged_abspath)
- {
- svn_boolean_t remains_in_conflict;
- const char *local_abspath;
-
- if (*external_failed)
- {
- *option_id = svn_client_conflict_option_postpone;
- break;
- }
-
- local_abspath = svn_client_conflict_get_local_abspath(conflict);
- err = svn_cl__merge_file_externally(base_abspath,
- their_abspath,
- my_abspath,
- merged_abspath,
- local_abspath,
- config,
- &remains_in_conflict,
- scratch_pool);
- if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL ||
- err->apr_err == SVN_ERR_EXTERNAL_PROGRAM))
- {
- char buf[1024];
- const char *message;
-
- message = svn_err_best_message(err, buf, sizeof(buf));
- SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
- message));
- *external_failed = TRUE;
- return svn_error_trace(err);
- }
- else if (err)
- return svn_error_trace(err);
-
- if (remains_in_conflict)
- *option_id = svn_client_conflict_option_postpone;
- else
- *option_id = svn_client_conflict_option_merged_text;
- break;
- }
- /* else, fall through to prompting. */
- break;
- }
-
- if (*option_id != svn_client_conflict_option_unspecified &&
- *option_id != svn_client_conflict_option_postpone)
- {
- SVN_ERR(mark_conflict_resolved(conflict, *option_id,
- text_conflicted,
- props_conflicted->nelts > 0 ? "" : NULL,
- tree_conflicted,
- path_prefix, conflict_stats,
- ctx, scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
resolve_conflict_interactively(svn_boolean_t *resolved,
svn_boolean_t *postponed,
svn_boolean_t *quit,
@@ -2011,23 +1876,24 @@ resolve_conflict_interactively(svn_boole
svn_error_t *
svn_cl__resolve_conflict(svn_boolean_t *resolved,
- svn_cl__accept_t *accept_which,
svn_boolean_t *quit,
svn_boolean_t *external_failed,
svn_boolean_t *printed_summary,
svn_client_conflict_t *conflict,
+ svn_cl__accept_t accept_which,
const char *editor_cmd,
apr_hash_t *config,
const char *path_prefix,
svn_cmdline_prompt_baton_t *pb,
svn_cl__conflict_stats_t *conflict_stats,
- svn_client_conflict_option_id_t option_id,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
svn_boolean_t text_conflicted;
apr_array_header_t *props_conflicted;
svn_boolean_t tree_conflicted;
+ const char *local_abspath;
+ svn_client_conflict_option_id_t option_id;
SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted,
&props_conflicted,
@@ -2035,59 +1901,225 @@ svn_cl__resolve_conflict(svn_boolean_t *
conflict,
scratch_pool,
scratch_pool));
+ local_abspath = svn_client_conflict_get_local_abspath(conflict);
- /* Resolve the conflict by --accept option or interactively if no
- * resolution option was passed. */
- if (option_id == svn_client_conflict_option_unspecified)
+ if (accept_which == svn_cl__accept_unspecified)
+ {
+ option_id = svn_client_conflict_option_unspecified;
+ }
+ else if (accept_which == svn_cl__accept_postpone)
{
- SVN_ERR(resolve_conflict_by_accept_option(&option_id, *accept_which,
- external_failed, conflict,
- editor_cmd, config,
- path_prefix, pb,
- conflict_stats, ctx,
- scratch_pool, scratch_pool));
+ option_id = svn_client_conflict_option_postpone;
+ }
+ else if (accept_which == svn_cl__accept_base)
+ {
+ option_id = svn_client_conflict_option_base_text;
+ }
+ else if (accept_which == svn_cl__accept_working)
+ {
+ option_id = svn_client_conflict_option_merged_text;
- if (option_id == svn_client_conflict_option_unspecified)
+ if (text_conflicted)
{
- svn_boolean_t postponed = FALSE;
- svn_boolean_t printed_description = FALSE;
- svn_error_t *err;
+ const char *mime_type =
+ svn_client_conflict_text_get_mime_type(conflict);
+
+ /* There is no merged text for binary conflicts, behave as
+ * if 'mine-full' was chosen. */
+ if (mime_type && svn_mime_type_is_binary(mime_type))
+ option_id = svn_client_conflict_option_working_text;
+ }
+ else if (tree_conflicted)
+ {
+ /* For tree conflicts, map 'working' to 'accept current working
+ * copy state'. */
+ option_id = svn_client_conflict_option_accept_current_wc_state;
+ }
+ }
+ else if (accept_which == svn_cl__accept_theirs_conflict)
+ {
+ option_id = svn_client_conflict_option_incoming_text_where_conflicted;
+ }
+ else if (accept_which == svn_cl__accept_mine_conflict)
+ {
+ option_id = svn_client_conflict_option_working_text_where_conflicted;
- *quit = FALSE;
+ if (tree_conflicted)
+ {
+ svn_wc_operation_t operation;
- /* We're in interactive mode and either the user gave no --accept
- option or the option did not apply; let's prompt. */
- while (!*resolved && !postponed && !*quit)
+ operation = svn_client_conflict_get_operation(conflict);
+ if (operation == svn_wc_operation_update ||
+ operation == svn_wc_operation_switch)
{
- err = resolve_conflict_interactively(resolved, &postponed, quit,
- external_failed,
- printed_summary,
- &printed_description,
- conflict,
- editor_cmd, config,
- path_prefix, pb,
- conflict_stats, ctx,
- scratch_pool, scratch_pool);
- if (err && err->apr_err == SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE)
+ svn_wc_conflict_reason_t reason;
+
+ reason = svn_client_conflict_get_local_change(conflict);
+ if (reason == svn_wc_conflict_reason_moved_away)
+ {
+ /* Map 'mine-conflict' to 'update move destination'. */
+ option_id =
+ svn_client_conflict_option_update_move_destination;
+ }
+ else if (reason == svn_wc_conflict_reason_deleted ||
+ reason == svn_wc_conflict_reason_replaced)
+ {
+ svn_wc_conflict_action_t action;
+ svn_node_kind_t node_kind;
+
+ action = svn_client_conflict_get_incoming_change(conflict);
+ node_kind =
+ svn_client_conflict_tree_get_victim_node_kind(conflict);
+
+ if (action == svn_wc_conflict_action_edit &&
+ node_kind == svn_node_dir)
+ {
+ /* Map 'mine-conflict' to 'update any moved away
+ * children'. */
+ option_id =
+ svn_client_conflict_option_update_any_moved_away_children;
+ }
+ }
+ }
+ }
+ }
+ else if (accept_which == svn_cl__accept_theirs_full)
+ {
+ option_id = svn_client_conflict_option_incoming_text;
+ }
+ else if (accept_which == svn_cl__accept_mine_full)
+ {
+ option_id = svn_client_conflict_option_working_text;
+ }
+ else if (accept_which == svn_cl__accept_edit)
+ {
+ option_id = svn_client_conflict_option_unspecified;
+
+ if (local_abspath)
+ {
+ if (*external_failed)
+ {
+ option_id = svn_client_conflict_option_postpone;
+ }
+ else
+ {
+ svn_error_t *err;
+
+ err = svn_cmdline__edit_file_externally(local_abspath,
+ editor_cmd, config,
+ scratch_pool);
+ if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR ||
+ err->apr_err == SVN_ERR_EXTERNAL_PROGRAM))
{
- /* Conflict resolution has failed. Let the user try again.
- * It is always possible to break out of this loop with
- * the 'quit' or 'postpone' options. */
- svn_handle_warning2(stderr, err, "svn: ");
+ char buf[1024];
+ const char *message;
+
+ message = svn_err_best_message(err, buf, sizeof(buf));
+ SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
+ message));
svn_error_clear(err);
- err = SVN_NO_ERROR;
+ *external_failed = TRUE;
}
- SVN_ERR(err);
+ else if (err)
+ return svn_error_trace(err);
+ option_id = svn_client_conflict_option_merged_text;
}
}
+ }
+ else if (accept_which == svn_cl__accept_launch)
+ {
+ const char *base_abspath = NULL;
+ const char *my_abspath = NULL;
+ const char *their_abspath = NULL;
+
+ option_id = svn_client_conflict_option_unspecified;
+
+ if (text_conflicted)
+ SVN_ERR(svn_client_conflict_text_get_contents(NULL, &my_abspath,
+ &base_abspath,
+ &their_abspath,
+ conflict, scratch_pool,
+ scratch_pool));
+
+ if (base_abspath && their_abspath && my_abspath && local_abspath)
+ {
+ if (*external_failed)
+ {
+ option_id = svn_client_conflict_option_postpone;
+ }
+ else
+ {
+ svn_boolean_t remains_in_conflict;
+ svn_error_t *err;
+
+ err = svn_cl__merge_file_externally(base_abspath, their_abspath,
+ my_abspath, local_abspath,
+ local_abspath, config,
+ &remains_in_conflict,
+ scratch_pool);
+ if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL ||
+ err->apr_err == SVN_ERR_EXTERNAL_PROGRAM))
+ {
+ char buf[1024];
+ const char *message;
+
+ message = svn_err_best_message(err, buf, sizeof(buf));
+ SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
+ message));
+ *external_failed = TRUE;
+ return svn_error_trace(err);
+ }
+ else if (err)
+ return svn_error_trace(err);
- return SVN_NO_ERROR;
+ if (remains_in_conflict)
+ option_id = svn_client_conflict_option_postpone;
+ else
+ option_id = svn_client_conflict_option_merged_text;
+ }
+ }
}
+ else
+ SVN_ERR_MALFUNCTION();
- /* Non-interactive resolution. */
- SVN_ERR_ASSERT(option_id != svn_client_conflict_option_unspecified);
+ /* If we are in interactive mode and either the user gave no --accept
+ * option or the option did not apply, then prompt. */
+ if (option_id == svn_client_conflict_option_unspecified)
+ {
+ svn_boolean_t postponed = FALSE;
+ svn_boolean_t printed_description = FALSE;
+ svn_error_t *err;
+
+ *quit = FALSE;
- if (option_id != svn_client_conflict_option_postpone)
+ while (!*resolved && !postponed && !*quit)
+ {
+ err = resolve_conflict_interactively(resolved, &postponed, quit,
+ external_failed,
+ printed_summary,
+ &printed_description,
+ conflict,
+ editor_cmd, config,
+ path_prefix, pb,
+ conflict_stats, ctx,
+ scratch_pool, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE)
+ {
+ /* Conflict resolution has failed. Let the user try again.
+ * It is always possible to break out of this loop with
+ * the 'quit' or 'postpone' options. */
+ svn_handle_warning2(stderr, err, "svn: ");
+ svn_error_clear(err);
+ err = SVN_NO_ERROR;
+ }
+ SVN_ERR(err);
+ }
+ }
+ else if (option_id == svn_client_conflict_option_postpone)
+ {
+ *resolved = FALSE;
+ }
+ else
{
SVN_ERR(mark_conflict_resolved(conflict, option_id,
text_conflicted,
@@ -2097,10 +2129,6 @@ svn_cl__resolve_conflict(svn_boolean_t *
ctx, scratch_pool));
*resolved = TRUE;
}
- else
- {
- *resolved = FALSE;
- }
return SVN_NO_ERROR;
}
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=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/info-cmd.c (original)
+++ subversion/branches/ra-git/subversion/svn/info-cmd.c Tue Dec 13 12:36:55 2016
@@ -811,7 +811,7 @@ print_info_item_revision(svn_revnum_t re
if (target_path)
SVN_ERR(svn_cmdline_printf(pool, "%-10ld %s", rev, target_path));
else
- SVN_ERR(svn_cmdline_printf(pool, "%-10ld", rev));
+ SVN_ERR(svn_cmdline_printf(pool, "%ld", rev));
}
else if (target_path)
SVN_ERR(svn_cmdline_printf(pool, "%-10s %s", "", target_path));
Modified: subversion/branches/ra-git/subversion/svn/list-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/list-cmd.c?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/list-cmd.c (original)
+++ subversion/branches/ra-git/subversion/svn/list-cmd.c Tue Dec 13 12:36:55 2016
@@ -351,6 +351,8 @@ svn_cl__list(apr_getopt_t *os,
const char *target = APR_ARRAY_IDX(targets, i, const char *);
const char *truepath;
svn_opt_revision_t peg_revision;
+ apr_array_header_t *patterns = NULL;
+ int k;
/* Initialize the following variables for
every list target. */
@@ -375,8 +377,27 @@ svn_cl__list(apr_getopt_t *os,
SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
}
- err = svn_client_list3(truepath, &peg_revision,
- &(opt_state->start_revision),
+ if (opt_state->search_patterns)
+ {
+ patterns = apr_array_make(subpool, 4, sizeof(const char *));
+ for (k = 0; k < opt_state->search_patterns->nelts; ++k)
+ {
+ apr_array_header_t *pattern_group
+ = APR_ARRAY_IDX(opt_state->search_patterns, k,
+ apr_array_header_t *);
+
+ /* Should never fail but ... */
+ if (pattern_group->nelts != 1)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'search-and' option is not supported"));
+
+ APR_ARRAY_PUSH(patterns, const char *)
+ = APR_ARRAY_IDX(pattern_group, 0, const char *);
+ }
+ }
+
+ err = svn_client_list4(truepath, &peg_revision,
+ &(opt_state->start_revision), patterns,
opt_state->depth,
dirent_fields,
(opt_state->xml || opt_state->verbose),
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=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/merge-cmd.c (original)
+++ subversion/branches/ra-git/subversion/svn/merge-cmd.c Tue Dec 13 12:36:55 2016
@@ -547,7 +547,7 @@ svn_cl__merge(apr_getopt_t *os,
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,
+ SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats,
opt_state, ctx, pool));
if (!opt_state->quiet)
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=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/resolve-cmd.c (original)
+++ subversion/branches/ra-git/subversion/svn/resolve-cmd.c Tue Dec 13 12:36:55 2016
@@ -43,12 +43,11 @@
struct conflict_status_walker_baton
{
svn_client_ctx_t *ctx;
- svn_client_conflict_option_id_t option_id;
svn_wc_notify_func2_t notify_func;
void *notify_baton;
svn_boolean_t resolved_one;
apr_hash_t *resolve_later;
- svn_cl__accept_t *accept_which;
+ svn_cl__accept_t accept_which;
svn_boolean_t *quit;
svn_boolean_t *external_failed;
svn_boolean_t *printed_summary;
@@ -141,14 +140,12 @@ conflict_status_walker(void *baton,
iterpool, iterpool));
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,
+ err = svn_cl__resolve_conflict(&resolved, cswb->quit, cswb->external_failed,
+ cswb->printed_summary, conflict,
+ cswb->accept_which, cswb->editor_cmd,
cswb->config, cswb->path_prefix,
cswb->pb, cswb->conflict_stats,
- cswb->option_id, cswb->ctx,
- scratch_pool);
+ cswb->ctx, scratch_pool);
if (err)
{
if (tree_conflicted)
@@ -175,8 +172,7 @@ static svn_error_t *
walk_conflicts(svn_client_ctx_t *ctx,
const char *local_abspath,
svn_depth_t depth,
- svn_client_conflict_option_id_t option_id,
- svn_cl__accept_t *accept_which,
+ svn_cl__accept_t accept_which,
svn_boolean_t *quit,
svn_boolean_t *external_failed,
svn_boolean_t *printed_summary,
@@ -195,7 +191,6 @@ walk_conflicts(svn_client_ctx_t *ctx,
depth = svn_depth_infinity;
cswb.ctx = ctx;
- cswb.option_id = option_id;
cswb.resolved_one = FALSE;
cswb.resolve_later = (depth != svn_depth_empty)
@@ -257,7 +252,6 @@ walk_conflicts(svn_client_ctx_t *ctx,
for (; hi && !err; hi = apr_hash_next(hi))
{
- const char *relpath;
svn_pool_clear(iterpool);
tc_abspath = apr_hash_this_key(hi);
@@ -265,24 +259,8 @@ walk_conflicts(svn_client_ctx_t *ctx,
if (ctx->cancel_func)
SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
- relpath = svn_dirent_skip_ancestor(local_abspath,
- tc_abspath);
-
- if (!relpath
- || (depth >= svn_depth_empty
- && depth < svn_depth_infinity
- && strchr(relpath, '/')))
- {
- continue;
- }
-
SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, tc_abspath,
iterpool, iterpool));
-
- if (depth == svn_depth_files
- && status->kind == svn_node_dir)
- continue;
-
err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath,
status, scratch_pool));
}
@@ -356,7 +334,6 @@ walk_conflicts(svn_client_ctx_t *ctx,
svn_error_t *
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)
@@ -365,7 +342,6 @@ svn_cl__walk_conflicts(apr_array_header_
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;
@@ -377,51 +353,6 @@ svn_cl__walk_conflicts(apr_array_header_
pb->cancel_func = ctx->cancel_func;
pb->cancel_baton = ctx->cancel_baton;
- switch (opt_state->accept_which)
- {
- case svn_cl__accept_working:
- option_id = svn_client_conflict_option_merged_text;
- break;
- case svn_cl__accept_base:
- option_id = svn_client_conflict_option_base_text;
- break;
- case svn_cl__accept_theirs_conflict:
- option_id = svn_client_conflict_option_incoming_text_where_conflicted;
- break;
- case svn_cl__accept_mine_conflict:
- option_id = svn_client_conflict_option_working_text_where_conflicted;
- break;
- case svn_cl__accept_theirs_full:
- option_id = svn_client_conflict_option_incoming_text;
- break;
- case svn_cl__accept_mine_full:
- option_id = svn_client_conflict_option_working_text;
- break;
- case svn_cl__accept_unspecified:
- 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_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"));
- }
-
-
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < targets->nelts; i++)
{
@@ -442,19 +373,18 @@ svn_cl__walk_conflicts(apr_array_header_
SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, ctx,
iterpool, iterpool));
err = svn_cl__resolve_conflict(&resolved,
- &opt_state->accept_which,
&quit, &external_failed,
&printed_summary,
- conflict, opt_state->editor_cmd,
+ conflict, opt_state->accept_which,
+ opt_state->editor_cmd,
ctx->config, path_prefix,
pb, conflict_stats,
- option_id, ctx,
- iterpool);
+ ctx, iterpool);
}
else
{
err = walk_conflicts(ctx, local_abspath, opt_state->depth,
- option_id, &opt_state->accept_which,
+ opt_state->accept_which,
&quit, &external_failed, &printed_summary,
opt_state->editor_cmd, ctx->config,
path_prefix, pb, conflict_stats, iterpool);
@@ -462,6 +392,16 @@ svn_cl__walk_conflicts(apr_array_header_
if (err)
{
+ svn_error_t *root = svn_error_root_cause(err);
+
+ if (root->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ /* ### Ignore. These errors can happen due to the working copy
+ * ### being re-arranged during tree conflict resolution. */
+ svn_error_clear(err);
+ continue;
+ }
+
svn_handle_warning2(stderr, svn_error_root_cause(err), "svn: ");
svn_error_clear(err);
had_error = TRUE;
@@ -507,7 +447,21 @@ svn_cl__resolve(apr_getopt_t *os,
SVN_ERR(svn_cl__check_targets_are_local_paths(targets));
- SVN_ERR(svn_cl__walk_conflicts(targets, conflict_stats, TRUE,
+ if (opt_state->accept_which == svn_cl__accept_unspecified &&
+ opt_state->non_interactive)
+ {
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("missing --accept option"));
+ }
+ else if (opt_state->accept_which == svn_cl__accept_postpone ||
+ opt_state->accept_which == svn_cl__accept_edit ||
+ opt_state->accept_which == svn_cl__accept_launch)
+ {
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("invalid 'accept' ARG"));
+ }
+
+ SVN_ERR(svn_cl__walk_conflicts(targets, conflict_stats,
opt_state, ctx, scratch_pool));
return SVN_NO_ERROR;
Modified: subversion/branches/ra-git/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svn/svn.c?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/svn.c (original)
+++ subversion/branches/ra-git/subversion/svn/svn.c Tue Dec 13 12:36:55 2016
@@ -143,7 +143,7 @@ typedef enum svn_cl__longopt_t {
opt_show_passwords,
opt_pin_externals,
opt_show_item,
- opt_adds_as_modification,
+ opt_adds_as_modification
} svn_cl__longopt_t;
@@ -798,7 +798,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
" Size (in bytes)\n"
" Date and time of the last commit\n"),
{'r', 'v', 'R', opt_depth, opt_incremental, opt_xml,
- opt_include_externals}, },
+ opt_include_externals, opt_search}, },
{ "lock", svn_cl__lock, {0}, N_
("Lock working copy paths or URLs in the repository, so that\n"
@@ -833,6 +833,17 @@ const svn_opt_subcommand_desc2_t svn_cl_
" reverse ranges is allowed.\n"
"\n"
" With -v, also print all affected paths with each log message.\n"
+ " Each changed path is preceded with a symbol describing the change:\n"
+ " A: The path was added or copied.\n"
+ " D: The path was deleted.\n"
+ " R: The path was replaced (deleted and re-added in the same revision).\n"
+ " M: The path's file and/or property content was modified.\n"
+ " If an added or replaced path was copied from somewhere else, the copy\n"
+ " source path and revision are shown in parentheses.\n"
+ " If a file or directory was moved from one path to another with 'svn move'\n"
+ " the old path will be listed as deleted and the new path will be listed\n"
+ " as copied from the old path at a prior revision.\n"
+ "\n"
" With -q, don't print the log message body itself (note that this is\n"
" compatible with -v).\n"
"\n"
@@ -885,7 +896,12 @@ const svn_opt_subcommand_desc2_t svn_cl_
"\n"
" Show the log message for the revision in which /branches/foo\n"
" was created:\n"
- " svn log --stop-on-copy --limit 1 -r0:HEAD ^/branches/foo\n"),
+ " svn log --stop-on-copy --limit 1 -r0:HEAD ^/branches/foo\n"
+ "\n"
+ " If ^/trunk/foo.c was moved to ^/trunk/bar.c' in revision 22, 'svn log -v'\n"
+ " shows a deletion and a copy in its changed paths list, such as:\n"
+ " D /trunk/foo.c\n"
+ " A /trunk/bar.c (from /trunk/foo.c:21)\n"),
{'r', 'c', 'q', 'v', 'g', opt_targets, opt_stop_on_copy, opt_incremental,
opt_xml, 'l', opt_with_all_revprops, opt_with_no_revprops,
opt_with_revprop, opt_depth, opt_diff, opt_diff_cmd,
@@ -1542,7 +1558,47 @@ const svn_opt_subcommand_desc2_t svn_cl_
"\n"
" The --accept=ARG option prevents interactive prompting and forces\n"
" conflicts on PATH to be resolved in the manner specified by ARG.\n"
- " In this mode, the command is not recursive by default (depth 'empty').\n"),
+ " In this mode, the command is not recursive by default (depth 'empty').\n"
+ "\n"
+ " A conflicted path cannot be committed with 'svn commit' until it\n"
+ " has been marked as resolved with 'svn resolve'.\n"
+ "\n"
+ " Subversion knows three types of conflicts:\n"
+ " Text conflicts, Property conflicts, and Tree conflicts.\n"
+ "\n"
+ " Text conflicts occur when overlapping changes to file contents were\n"
+ " made. Text conflicts are usually resolved by editing the conflicted\n"
+ " file or by using a merge tool (which may be an external program).\n"
+ " 'svn resolve' provides options which can be used to automatically\n"
+ " edit files (such as 'mine-full' or 'theirs-conflict'), but these are\n"
+ " only useful in situations where it is acceptable to discard local or\n"
+ " incoming changes altogether.\n"
+ "\n"
+ " Property conflicts are usually resolved by editing the value of the\n"
+ " conflicted property (either from the interactive prompt, or with\n"
+ " 'svn propedit'). As with text conflicts, options exist to edit a\n"
+ " property automatically, discarding some changes in favour of others.\n"
+ "\n"
+ " Tree conflicts occur when a change to the directory structure was\n"
+ " made, and when this change cannot be applied to the working copy\n"
+ " without affecting other changes (text changes, property changes,\n"
+ " or other changes to the directory structure). Brief information about\n" " tree conflicts is shown by the 'svn status' and'svn info' commands.\n"
+ " In interactive mode, 'svn resolve' will attempt to describe tree conflicts\n"
+ " in detail, and may offer options to resolve the conflict automatically.\n"
+ " It is recommended to use these automatic options whenever possible,\n"
+ " rather than attempting manual tree conflict resolution.\n"
+ "\n"
+ " If a tree conflict cannot be resolved automatically, it is recommended\n"
+ " to figure out why the conflict occurred before attempting to resolve it.\n"
+ " The 'svn log -v' command can be used to inspect structural changes\n"
+ " made in past revisions, and perhaps even on other branches.\n"
+ " 'svn help log' describes how these structural changes are presented.\n"
+ " Once the conflicting \"incoming\" change has been identified with 'svn log'\n"
+ " the current \"local\" working copy state should be examined and adjusted\n"
+ " in a way such that the conflict is resolved. This may involve editing\n"
+ " files manually or with 'svn merge'. It may be necessary to discard some\n"
+ " local changes with 'svn revert'. Files or directories might have to be\n"
+ " copied, deleted, or moved.\n"),
{opt_targets, 'R', opt_depth, 'q', opt_accept},
{{opt_accept, N_("specify automatic conflict resolution source\n"
" "
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=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/switch-cmd.c (original)
+++ subversion/branches/ra-git/subversion/svn/switch-cmd.c Tue Dec 13 12:36:55 2016
@@ -195,7 +195,7 @@ svn_cl__switch(apr_getopt_t *os,
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,
+ SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats,
opt_state, ctx, scratch_pool));
if (! opt_state->quiet)
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=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svn/update-cmd.c (original)
+++ subversion/branches/ra-git/subversion/svn/update-cmd.c Tue Dec 13 12:36:55 2016
@@ -185,7 +185,7 @@ svn_cl__update(apr_getopt_t *os,
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,
+ SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats,
opt_state, ctx, scratch_pool));
if (! opt_state->quiet)
Modified: subversion/branches/ra-git/subversion/svnbench/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnbench/cl.h?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnbench/cl.h (original)
+++ subversion/branches/ra-git/subversion/svnbench/cl.h Tue Dec 13 12:36:55 2016
@@ -95,6 +95,7 @@ typedef struct svn_cl__opt_state_t
svn_boolean_t trust_server_cert_expired;
svn_boolean_t trust_server_cert_not_yet_valid;
svn_boolean_t trust_server_cert_other_failure;
+ apr_array_header_t* search_patterns; /* pattern arguments for --search */
} svn_cl__opt_state_t;
Modified: subversion/branches/ra-git/subversion/svnbench/null-list-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnbench/null-list-cmd.c?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnbench/null-list-cmd.c (original)
+++ subversion/branches/ra-git/subversion/svnbench/null-list-cmd.c Tue Dec 13 12:36:55 2016
@@ -122,6 +122,8 @@ svn_cl__null_list(apr_getopt_t *os,
const char *target = APR_ARRAY_IDX(targets, i, const char *);
const char *truepath;
svn_opt_revision_t peg_revision;
+ apr_array_header_t *patterns = NULL;
+ int k;
svn_pool_clear(subpool);
@@ -131,8 +133,27 @@ svn_cl__null_list(apr_getopt_t *os,
SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
subpool));
- err = svn_client_list3(truepath, &peg_revision,
- &(opt_state->start_revision),
+ if (opt_state->search_patterns)
+ {
+ patterns = apr_array_make(subpool, 4, sizeof(const char *));
+ for (k = 0; k < opt_state->search_patterns->nelts; ++k)
+ {
+ apr_array_header_t *pattern_group
+ = APR_ARRAY_IDX(opt_state->search_patterns, k,
+ apr_array_header_t *);
+
+ /* Should never fail but ... */
+ if (pattern_group->nelts != 1)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'search-and' option is not supported"));
+
+ APR_ARRAY_PUSH(patterns, const char *)
+ = APR_ARRAY_IDX(pattern_group, 0, const char *);
+ }
+ }
+
+ err = svn_client_list4(truepath, &peg_revision,
+ &(opt_state->start_revision), patterns,
opt_state->depth,
dirent_fields,
opt_state->verbose,
Modified: subversion/branches/ra-git/subversion/svnbench/svnbench.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnbench/svnbench.c?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnbench/svnbench.c (original)
+++ subversion/branches/ra-git/subversion/svnbench/svnbench.c Tue Dec 13 12:36:55 2016
@@ -41,6 +41,7 @@
#include "private/svn_opt_private.h"
#include "private/svn_cmdline_private.h"
#include "private/svn_string_private.h"
+#include "private/svn_utf_private.h"
#include "svn_private_config.h"
@@ -67,7 +68,8 @@ typedef enum svn_cl__longopt_t {
opt_with_no_revprops,
opt_trust_server_cert,
opt_trust_server_cert_failures,
- opt_changelist
+ opt_changelist,
+ opt_search
} svn_cl__longopt_t;
@@ -164,6 +166,8 @@ const apr_getopt_option_t svn_cl__option
N_("use/display additional information from merge\n"
" "
"history")},
+ {"search", opt_search, 1,
+ N_("use ARG as search pattern (glob syntax)")},
/* Long-opt Aliases
*
@@ -256,7 +260,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
" If locked, the letter 'O'. (Use 'svn info URL' to see details)\n"
" Size (in bytes)\n"
" Date and time of the last commit\n"),
- {'r', 'v', 'q', 'R', opt_depth} },
+ {'r', 'v', 'q', 'R', opt_depth, opt_search} },
{ "null-log", svn_cl__null_log, {0}, N_
("Fetch the log messages for a set of revision(s) and/or path(s).\n"
@@ -345,6 +349,24 @@ ra_progress_func(apr_off_t progress,
/* Our cancellation callback. */
svn_cancel_func_t svn_cl__check_cancel = NULL;
+/* Add a --search argument to OPT_STATE.
+ * These options start a new search pattern group. */
+static void
+add_search_pattern_group(svn_cl__opt_state_t *opt_state,
+ const char *pattern,
+ apr_pool_t *result_pool)
+{
+ apr_array_header_t *group = NULL;
+
+ if (opt_state->search_patterns == NULL)
+ opt_state->search_patterns = apr_array_make(result_pool, 1,
+ sizeof(apr_array_header_t *));
+
+ group = apr_array_make(result_pool, 1, sizeof(const char *));
+ APR_ARRAY_PUSH(group, const char *) = pattern;
+ APR_ARRAY_PUSH(opt_state->search_patterns, apr_array_header_t *) = group;
+}
+
/*** Main. ***/
@@ -371,9 +393,13 @@ sub_main(int *exit_code, int argc, const
svn_boolean_t use_notifier = TRUE;
apr_time_t start_time, time_taken;
ra_progress_baton_t ra_progress_baton = {0};
+ svn_membuf_t buf;
received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
+ /* Init the temporary buffer. */
+ svn_membuf__create(&buf, 0, pool);
+
/* Check library versions */
SVN_ERR(check_lib_versions());
@@ -656,6 +682,14 @@ sub_main(int *exit_code, int argc, const
case 'g':
opt_state.use_merge_history = TRUE;
break;
+ case opt_search:
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, 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;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
Modified: subversion/branches/ra-git/subversion/svnmucc/svnmucc.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnmucc/svnmucc.c?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnmucc/svnmucc.c (original)
+++ subversion/branches/ra-git/subversion/svnmucc/svnmucc.c Tue Dec 13 12:36:55 2016
@@ -480,7 +480,7 @@ sub_main(int *exit_code, int argc, const
non_interactive_opt,
force_interactive_opt,
trust_server_cert_opt,
- trust_server_cert_failures_opt,
+ trust_server_cert_failures_opt
};
static const apr_getopt_option_t options[] = {
{"message", 'm', 1, ""},
Modified: subversion/branches/ra-git/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnserve/serve.c?rev=1773992&r1=1773991&r2=1773992&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnserve/serve.c (original)
+++ subversion/branches/ra-git/subversion/svnserve/serve.c Tue Dec 13 12:36:55 2016
@@ -1679,11 +1679,11 @@ get_file(svn_ra_svn_conn_t *conn,
return SVN_NO_ERROR;
}
+/* Translate all the words in DIRENT_FIELDS_LIST into the flags in
+ * DIRENT_FIELDS_P. If DIRENT_FIELDS_LIST is NULL, set all flags. */
static svn_error_t *
-get_dir(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- svn_ra_svn__list_t *params,
- void *baton)
+parse_dirent_fields(apr_uint64_t *dirent_fields_p,
+ svn_ra_svn__list_t *dirent_fields_list)
{
static const svn_string_t str_kind
= SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_KIND);
@@ -1698,32 +1698,7 @@ get_dir(svn_ra_svn_conn_t *conn,
static const svn_string_t str_last_author
= SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_LAST_AUTHOR);
- server_baton_t *b = baton;
- const char *path, *full_path;
- svn_revnum_t rev;
- apr_hash_t *entries, *props = NULL;
- apr_array_header_t *inherited_props;
- apr_hash_index_t *hi;
- svn_fs_root_t *root;
- apr_pool_t *subpool;
- svn_boolean_t want_props, want_contents;
- apr_uint64_t wants_inherited_props;
apr_uint64_t dirent_fields;
- svn_ra_svn__list_t *dirent_fields_list = NULL;
- svn_ra_svn__item_t *elt;
- int i;
- authz_baton_t ab;
-
- ab.server = b;
- ab.conn = conn;
-
- SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)bb?l?B", &path, &rev,
- &want_props, &want_contents,
- &dirent_fields_list,
- &wants_inherited_props));
-
- if (wants_inherited_props == SVN_RA_SVN_UNSPECIFIED_NUMBER)
- wants_inherited_props = FALSE;
if (! dirent_fields_list)
{
@@ -1731,15 +1706,17 @@ get_dir(svn_ra_svn_conn_t *conn,
}
else
{
+ int i;
dirent_fields = 0;
for (i = 0; i < dirent_fields_list->nelts; ++i)
{
- elt = &SVN_RA_SVN__LIST_ITEM(dirent_fields_list, i);
+ svn_ra_svn__item_t *elt
+ = &SVN_RA_SVN__LIST_ITEM(dirent_fields_list, i);
if (elt->kind != SVN_RA_SVN_WORD)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
- "Dirent field not a string");
+ "Dirent field not a word");
if (svn_string_compare(&str_kind, &elt->u.word))
dirent_fields |= SVN_DIRENT_KIND;
@@ -1756,6 +1733,43 @@ get_dir(svn_ra_svn_conn_t *conn,
}
}
+ *dirent_fields_p = dirent_fields;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+get_dir(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
+{
+ server_baton_t *b = baton;
+ const char *path, *full_path;
+ svn_revnum_t rev;
+ apr_hash_t *entries, *props = NULL;
+ apr_array_header_t *inherited_props;
+ apr_hash_index_t *hi;
+ svn_fs_root_t *root;
+ apr_pool_t *subpool;
+ svn_boolean_t want_props, want_contents;
+ apr_uint64_t wants_inherited_props;
+ apr_uint64_t dirent_fields;
+ svn_ra_svn__list_t *dirent_fields_list = NULL;
+ int i;
+ authz_baton_t ab;
+
+ ab.server = b;
+ ab.conn = conn;
+
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)bb?l?B", &path, &rev,
+ &want_props, &want_contents,
+ &dirent_fields_list,
+ &wants_inherited_props));
+
+ if (wants_inherited_props == SVN_RA_SVN_UNSPECIFIED_NUMBER)
+ wants_inherited_props = FALSE;
+
+ SVN_ERR(parse_dirent_fields(&dirent_fields, dirent_fields_list));
full_path = svn_fspath__join(b->repository->fs_path->data,
svn_relpath_canonicalize(path, pool), pool);
@@ -3524,6 +3538,114 @@ get_inherited_props(svn_ra_svn_conn_t *c
return SVN_NO_ERROR;
}
+/* Baton type to be used with list_receiver. */
+typedef struct list_receiver_baton_t
+{
+ /* Send the data through this connection. */
+ svn_ra_svn_conn_t *conn;
+
+ /* Send the field selected by these flags. */
+ apr_uint64_t dirent_fields;
+} list_receiver_baton_t;
+
+/* Implements svn_repos_dirent_receiver_t, sending DIRENT and PATH to the
+ * client. BATON must be a list_receiver_baton_t. */
+static svn_error_t *
+list_receiver(const char *path,
+ svn_dirent_t *dirent,
+ void *baton,
+ apr_pool_t *pool)
+{
+ list_receiver_baton_t *b = baton;
+ return svn_error_trace(svn_ra_svn__write_dirent(b->conn, pool, path, dirent,
+ b->dirent_fields));
+}
+
+static svn_error_t *
+list(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ svn_ra_svn__list_t *params,
+ void *baton)
+{
+ server_baton_t *b = baton;
+ const char *path, *full_path;
+ svn_revnum_t rev;
+ svn_depth_t depth;
+ apr_array_header_t *patterns = NULL;
+ svn_fs_root_t *root;
+ const char *depth_word;
+ svn_boolean_t path_info_only;
+ svn_ra_svn__list_t *dirent_fields_list = NULL;
+ svn_ra_svn__list_t *patterns_list = NULL;
+ int i;
+ list_receiver_baton_t rb;
+ svn_error_t *err, *write_err;
+
+ authz_baton_t ab;
+ ab.server = b;
+ ab.conn = conn;
+
+ /* Read the command parameters. */
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)w?l?l", &path, &rev,
+ &depth_word, &dirent_fields_list,
+ &patterns_list));
+
+ rb.conn = conn;
+ SVN_ERR(parse_dirent_fields(&rb.dirent_fields, dirent_fields_list));
+
+ depth = svn_depth_from_word(depth_word);
+ full_path = svn_fspath__join(b->repository->fs_path->data,
+ svn_relpath_canonicalize(path, pool), pool);
+
+ /* Read the patterns list. */
+ if (patterns_list)
+ {
+ patterns = apr_array_make(pool, 0, sizeof(const char *));
+ for (i = 0; i < patterns_list->nelts; ++i)
+ {
+ svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(patterns_list, i);
+
+ if (elt->kind != SVN_RA_SVN_STRING)
+ return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ "Pattern field not a string");
+
+ APR_ARRAY_PUSH(patterns, const char *) = elt->u.string.data;
+ }
+ }
+
+ /* Check authorizations */
+ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read,
+ full_path, FALSE));
+
+ if (!SVN_IS_VALID_REVNUM(rev))
+ SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->repository->fs, pool));
+
+ SVN_ERR(log_command(b, conn, pool, "%s",
+ svn_log__list(full_path, rev, patterns, depth,
+ rb.dirent_fields, pool)));
+
+ /* Fetch the root of the appropriate revision. */
+ SVN_CMD_ERR(svn_fs_revision_root(&root, b->repository->fs, rev, pool));
+
+ /* Fetch the directory entries if requested and send them immediately. */
+ path_info_only = (rb.dirent_fields & ~SVN_DIRENT_KIND) == 0;
+ err = svn_repos_list(root, full_path, patterns, depth, path_info_only,
+ authz_check_access_cb_func(b), &ab, list_receiver,
+ &rb, NULL, NULL, pool);
+
+
+ /* Finish response. */
+ write_err = svn_ra_svn__write_word(conn, pool, "done");
+ if (write_err)
+ {
+ svn_error_clear(err);
+ return write_err;
+ }
+ SVN_CMD_ERR(err);
+
+ return svn_error_trace(svn_ra_svn__write_cmd_response(conn, pool, ""));
+}
+
static const svn_ra_svn__cmd_entry_t main_commands[] = {
{ "reparent", reparent },
{ "get-latest-rev", get_latest_rev },
@@ -3556,6 +3678,7 @@ static const svn_ra_svn__cmd_entry_t mai
{ "replay-range", replay_range },
{ "get-deleted-rev", get_deleted_rev },
{ "get-iprops", get_inherited_props },
+ { "list", list },
{ NULL }
};
@@ -3747,6 +3870,7 @@ find_repos(const char *url,
if (hooks_env)
hooks_env = svn_dirent_internal_style(hooks_env, scratch_pool);
+ SVN_ERR(svn_repos_hooks_setenv(repository->repos, hooks_env, scratch_pool));
repository->hooks_env = apr_pstrdup(result_pool, hooks_env);
return SVN_NO_ERROR;
@@ -3954,7 +4078,7 @@ construct_server_baton(server_baton_t **
* send an empty mechlist. */
if (params->compression_level > 0)
SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool,
- "nn()(wwwwwwwwwww)",
+ "nn()(wwwwwwwwwwww)",
(apr_uint64_t) 2, (apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
SVN_RA_SVN_CAP_SVNDIFF1,
@@ -3966,11 +4090,12 @@ construct_server_baton(server_baton_t **
SVN_RA_SVN_CAP_PARTIAL_REPLAY,
SVN_RA_SVN_CAP_INHERITED_PROPS,
SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS,
- SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE
+ SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE,
+ SVN_RA_SVN_CAP_LIST
));
else
SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool,
- "nn()(wwwwwwwwww)",
+ "nn()(wwwwwwwwwww)",
(apr_uint64_t) 2, (apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
SVN_RA_SVN_CAP_ABSENT_ENTRIES,
@@ -3981,7 +4106,8 @@ construct_server_baton(server_baton_t **
SVN_RA_SVN_CAP_PARTIAL_REPLAY,
SVN_RA_SVN_CAP_INHERITED_PROPS,
SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS,
- SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE
+ SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE,
+ SVN_RA_SVN_CAP_LIST
));
/* Read client response, which we assume to be in version 2 format: