summaryrefslogtreecommitdiff
path: root/subversion/svn/svn.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svn/svn.c')
-rw-r--r--subversion/svn/svn.c803
1 files changed, 480 insertions, 323 deletions
diff --git a/subversion/svn/svn.c b/subversion/svn/svn.c
index 38d4ce1..058be70 100644
--- a/subversion/svn/svn.c
+++ b/subversion/svn/svn.c
@@ -110,7 +110,7 @@ typedef enum svn_cl__longopt_t {
opt_remove,
opt_revprop,
opt_stop_on_copy,
- opt_strict,
+ opt_strict, /* ### DEPRECATED */
opt_targets,
opt_depth,
opt_set_depth,
@@ -125,6 +125,7 @@ typedef enum svn_cl__longopt_t {
opt_show_revs,
opt_reintegrate,
opt_trust_server_cert,
+ opt_trust_server_cert_failures,
opt_strip,
opt_ignore_keywords,
opt_reverse_diff,
@@ -134,7 +135,14 @@ typedef enum svn_cl__longopt_t {
opt_include_externals,
opt_show_inherited_props,
opt_search,
- opt_search_and
+ opt_search_and,
+ opt_mergeinfo_log,
+ opt_remove_unversioned,
+ opt_remove_ignored,
+ opt_no_newline,
+ opt_show_passwords,
+ opt_pin_externals,
+ opt_show_item,
} svn_cl__longopt_t;
@@ -186,7 +194,10 @@ const apr_getopt_option_t svn_cl__options[] =
{"verbose", 'v', 0, N_("print extra information")},
{"show-updates", 'u', 0, N_("display update information")},
{"username", opt_auth_username, 1, N_("specify a username ARG")},
- {"password", opt_auth_password, 1, N_("specify a password ARG")},
+ {"password", opt_auth_password, 1,
+ N_("specify a password ARG (caution: on many operating\n"
+ " "
+ "systems, other users will be able to see this)")},
{"extensions", 'x', 1,
N_("Specify differencing options for external diff or\n"
" "
@@ -204,6 +215,8 @@ const apr_getopt_option_t svn_cl__options[] =
" "
" --ignore-eol-style: Ignore changes in EOL style\n"
" "
+ " -U ARG, --context ARG: Show ARG lines of context\n"
+ " "
" -p, --show-c-function: Show C function name")},
{"targets", opt_targets, 1,
N_("pass contents of file ARG as additional args")},
@@ -216,7 +229,7 @@ const apr_getopt_option_t svn_cl__options[] =
" "
"'empty', 'files', 'immediates', or 'infinity')")},
{"xml", opt_xml, 0, N_("output in XML")},
- {"strict", opt_strict, 0, N_("use strict semantics")},
+ {"strict", opt_strict, 0, N_("DEPRECATED")},
{"stop-on-copy", opt_stop_on_copy, 0,
N_("do not cross copies while traversing history")},
{"no-ignore", opt_no_ignore, 0,
@@ -226,11 +239,23 @@ const apr_getopt_option_t svn_cl__options[] =
{"no-auth-cache", opt_no_auth_cache, 0,
N_("do not cache authentication tokens")},
{"trust-server-cert", opt_trust_server_cert, 0,
- N_("accept SSL server certificates from unknown\n"
+ N_("deprecated; same as\n"
+ " "
+ "--trust-server-cert-failures=unknown-ca")},
+ {"trust-server-cert-failures", opt_trust_server_cert_failures, 1,
+ N_("with --non-interactive, accept SSL server\n"
+ " "
+ "certificates with failures; ARG is comma-separated\n"
+ " "
+ "list of 'unknown-ca' (Unknown Authority),\n"
" "
- "certificate authorities without prompting (but only\n"
+ "'cn-mismatch' (Hostname mismatch), 'expired'\n"
" "
- "with '--non-interactive')") },
+ "(Expired certificate), 'not-yet-valid' (Not yet\n"
+ " "
+ "valid certificate) and 'other' (all other not\n"
+ " "
+ "separately classified certificate errors).")},
{"non-interactive", opt_non_interactive, 0,
N_("do no interactive prompting (default is to prompt\n"
" "
@@ -369,17 +394,36 @@ const apr_getopt_option_t svn_cl__options[] =
" "
"Please run 'svn update' instead.")},
{"include-externals", opt_include_externals, 0,
- N_("Also commit file and dir externals reached by\n"
+ N_("also operate on externals defined by\n"
" "
- "recursion. This does not include externals with a\n"
- " "
- "fixed revision. (See the svn:externals property)")},
+ "svn:externals properties")},
{"show-inherited-props", opt_show_inherited_props, 0,
- N_("retrieve target's inherited properties")},
+ N_("retrieve properties set on parents of the target")},
{"search", opt_search, 1,
N_("use ARG as search pattern (glob syntax)")},
{"search-and", opt_search_and, 1,
N_("combine ARG with the previous search pattern")},
+ {"log", opt_mergeinfo_log, 0,
+ N_("show revision log message, author and date")},
+ {"remove-unversioned", opt_remove_unversioned, 0,
+ N_("remove unversioned items")},
+ {"remove-ignored", opt_remove_ignored, 0, N_("remove ignored items")},
+ {"no-newline", opt_no_newline, 0, N_("do not output the trailing newline")},
+ {"show-passwords", opt_show_passwords, 0, N_("show cached passwords")},
+ {"pin-externals", opt_pin_externals, 0,
+ N_("pin externals with no explicit revision to their\n"
+ " "
+ "current revision (recommended when tagging)")},
+ {"show-item", opt_show_item, 1,
+ N_("print only the item identified by ARG ('kind',\n"
+ " "
+ "'url', 'relative-url', 'repos-root-url',\n"
+ " "
+ "'repos-uuid', 'revision', 'last-changed-revision',\n"
+ " "
+ "'last-changed-date', 'last-changed-author',\n"
+ " "
+ "'wc-root')")},
/* Long-opt Aliases
*
@@ -412,8 +456,9 @@ const apr_getopt_option_t svn_cl__options[] =
willy-nilly to every invocation of 'svn') . */
const int svn_cl__global_options[] =
{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive,
- opt_force_interactive, opt_trust_server_cert, opt_config_dir,
- opt_config_options, 0
+ opt_force_interactive, opt_trust_server_cert,
+ opt_trust_server_cert_failures,
+ opt_config_dir, opt_config_options, 0
};
/* Options for giving a log message. (Some of these also have other uses.)
@@ -434,13 +479,54 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
opt_no_autoprops, opt_parents },
{{opt_parents, N_("add intermediate parents")}} },
+ { "auth", svn_cl__auth, {0}, N_
+ ("Manage cached authentication credentials.\n"
+ "usage: 1. svn auth [PATTERN ...]\n"
+ "usage: 2. svn auth --remove PATTERN [PATTERN ...]\n"
+ "\n"
+ " With no arguments, list all cached authentication credentials.\n"
+ " Authentication credentials include usernames, passwords,\n"
+ " SSL certificates, and SSL client-certificate passphrases.\n"
+ " If PATTERN is specified, only list credentials with attributes matching one\n"
+ " or more patterns. With the --remove option, remove cached authentication\n"
+ " credentials matching one or more patterns.\n"
+ "\n"
+ " If more than one pattern is specified credentials are considered only they\n"
+ " match all specified patterns. Patterns are matched case-sensitively and may\n"
+ " contain glob wildcards:\n"
+ " ? matches any single character\n"
+ " * matches a sequence of arbitrary characters\n"
+ " [abc] matches any of the characters listed inside the brackets\n"
+ " Note that wildcards will usually need to be quoted or escaped on the\n"
+ " command line because many command shells will interfere by trying to\n"
+ " expand them.\n"),
+ { opt_remove, opt_show_passwords },
+ { {opt_remove, N_("remove matching authentication credentials")} }
+
+ },
+
{ "blame", svn_cl__blame, {"praise", "annotate", "ann"}, N_
- ("Output the content of specified files or\n"
- "URLs with revision and author information in-line.\n"
- "usage: blame TARGET[@REV]...\n"
+ ("Show when each line of a file was last (or\n"
+ "next) changed.\n"
+ "usage: blame [-rM:N] TARGET[@REV]...\n"
+ "\n"
+ " Annotate each line of a file with the revision number and author of the\n"
+ " last change (or optionally the next change) to that line.\n"
+ "\n"
+ " With no revision range (same as -r0:REV), or with '-r M:N' where M < N,\n"
+ " annotate each line that is present in revision N of the file, with\n"
+ " the last revision at or before rN that changed or added the line,\n"
+ " looking back no further than rM.\n"
+ "\n"
+ " With a reverse revision range '-r M:N' where M > N,\n"
+ " annotate each line that is present in revision N of the file, with\n"
+ " the next revision after rN that changed or deleted the line,\n"
+ " looking forward no further than rM.\n"
"\n"
" If specified, REV determines in which revision the target is first\n"
- " looked up.\n"),
+ " looked up.\n"
+ "\n"
+ " Write the annotated result to standard output.\n"),
{'r', 'v', 'g', opt_incremental, opt_xml, 'x', opt_force} },
{ "cat", svn_cl__cat, {0}, N_
@@ -449,7 +535,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
"\n"
" If specified, REV determines in which revision the target is first\n"
" looked up.\n"),
- {'r'} },
+ {'r', opt_ignore_keywords} },
{ "changelist", svn_cl__changelist, {"cl"}, N_
("Associate (or dissociate) changelist CLNAME with the named files.\n"
@@ -489,16 +575,25 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
"unfinished operations, etc.\n"
"usage: cleanup [WCPATH...]\n"
"\n"
- " Finish any unfinished business in the working copy at WCPATH, and remove\n"
- " write locks (shown as 'L' by the 'svn status' command) from the working\n"
- " copy. Usually, this is only necessary if a Subversion client has crashed\n"
- " while using the working copy, leaving it in an unusable state.\n"
+ " By default, finish any unfinished business in the working copy at WCPATH,\n"
+ " and remove write locks (shown as 'L' by the 'svn status' command) from\n"
+ " the working copy. Usually, this is only necessary if a Subversion client\n"
+ " has crashed while using the working copy, leaving it in an unusable state.\n"
"\n"
" WARNING: There is no mechanism that will protect write locks still\n"
" being used by other Subversion clients. Running this command\n"
" while another client is using the working copy can corrupt\n"
- " the working copy beyond repair!\n"),
- {opt_merge_cmd} },
+ " the working copy beyond repair!\n"
+ "\n"
+ " If the --remove-unversioned option or the --remove-ignored option\n"
+ " is given, remove any unversioned or ignored items within WCPATH.\n"
+ " To prevent accidental working copy corruption, unversioned or ignored\n"
+ " items can only be removed if the working copy is not already locked\n"
+ " for writing by another Subversion client.\n"
+ " Note that the 'svn status' command shows unversioned items as '?',\n"
+ " and ignored items as 'I' if the --no-ignore option is given to it.\n"),
+ {opt_merge_cmd, opt_remove_unversioned, opt_remove_ignored,
+ opt_include_externals, 'q'} },
{ "commit", svn_cl__commit, {"ci"},
N_("Send changes from your working copy to the repository.\n"
@@ -507,7 +602,11 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" A log message must be provided, but it can be empty. If it is not\n"
" given by a --message or --file option, an editor will be started.\n"
" If any targets are (or contain) locked items, those will be\n"
- " unlocked after a successful commit.\n"),
+ " unlocked after a successful commit.\n"
+ "\n"
+ " If --include-externals is given, also commit file and directory\n"
+ " externals reached by recursion. Do not commit externals with a\n"
+ " fixed revision.\n"),
{'q', 'N', opt_depth, opt_targets, opt_no_unlock, SVN_CL__LOG_MSG_OPTIONS,
opt_changelist, opt_keep_changelists, opt_include_externals} },
@@ -528,7 +627,8 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" contact the repository. As such, they may not, by default, be able\n"
" to propagate merge tracking information from the source of the copy\n"
" to the destination.\n"),
- {'r', 'q', opt_ignore_externals, opt_parents, SVN_CL__LOG_MSG_OPTIONS} },
+ {'r', 'q', opt_ignore_externals, opt_parents, SVN_CL__LOG_MSG_OPTIONS,
+ opt_pin_externals} },
{ "delete", svn_cl__delete, {"del", "remove", "rm"}, N_
("Remove files and directories from version control.\n"
@@ -635,8 +735,24 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
"\n"
" Print information about each TARGET (default: '.').\n"
" TARGET may be either a working-copy path or URL. If specified, REV\n"
- " determines in which revision the target is first looked up.\n"),
- {'r', 'R', opt_depth, opt_targets, opt_incremental, opt_xml, opt_changelist}
+ " determines in which revision the target is first looked up.\n"
+ "\n"
+ " With --show-item, print only the value of one item of information\n"
+ " about TARGET. One of the following items can be selected:\n"
+ " kind the kind of TARGET\n"
+ " url the URL of TARGET in the repository\n"
+ " relative-url the repository-relative URL\n"
+ " repos-root-url the repository root URL\n"
+ " repos-uuid the repository UUID\n"
+ " revision the revision of TARGET (defaults to BASE\n"
+ " for working copy paths and HEAD for URLs)\n"
+ " last-changed-revision the most recent revision in which TARGET\n"
+ " was changed\n"
+ " last-changed-date the date of the last-changed revision\n"
+ " last-changed-author the author of the last-changed revision\n"
+ " wc-root the root of TARGET's working copy\n"),
+ {'r', 'R', opt_depth, opt_targets, opt_incremental, opt_xml,
+ opt_changelist, opt_include_externals, opt_show_item, opt_no_newline}
},
{ "list", svn_cl__list, {"ls"}, N_
@@ -659,8 +775,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" 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, N_("include externals definitions")}} },
+ opt_include_externals}, },
{ "lock", svn_cl__lock, {0}, N_
("Lock working copy paths or URLs in the repository, so that\n"
@@ -748,12 +863,14 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" 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"),
- {'r', 'q', 'v', 'g', 'c', 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, opt_internal_diff, 'x', opt_search,
- opt_search_and, },
+ {'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,
+ opt_internal_diff, 'x', opt_search, opt_search_and },
{{opt_with_revprop, N_("retrieve revision property ARG")},
- {'c', N_("the change made in revision ARG")}} },
+ {'c', N_("the change made in revision ARG")},
+ {'v', N_("also print all affected paths")},
+ {'q', N_("do not print the log message")}} },
{ "merge", svn_cl__merge, {0}, N_
( /* For this large section, let's keep it unindented for easier
@@ -1088,7 +1205,9 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" repositories.\n"),
{'r', 'c', 'N', opt_depth, 'q', opt_force, opt_dry_run, opt_merge_cmd,
opt_record_only, 'x', opt_ignore_ancestry, opt_accept, opt_reintegrate,
- opt_allow_mixed_revisions, 'v'} },
+ opt_allow_mixed_revisions, 'v'},
+ { { opt_force, N_("force deletions even if deleted contents don't match") } }
+ },
{ "mergeinfo", svn_cl__mergeinfo, {0}, N_
("Display merge-related information.\n"
@@ -1119,7 +1238,8 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" and the default for TARGET is HEAD for a URL or BASE for a WC path.\n"
"\n"
" The depth can be 'empty' or 'infinity'; the default is 'empty'.\n"),
- {'r', 'R', opt_depth, opt_show_revs} },
+ {'r', 'R', 'q', 'v', opt_depth, opt_show_revs, opt_mergeinfo_log,
+ opt_incremental } },
{ "mkdir", svn_cl__mkdir, {0}, N_
("Create a new directory under version control.\n"
@@ -1215,7 +1335,9 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
"\n"
" 1. Removes versioned props in working copy.\n"
" 2. Removes unversioned remote prop on repos revision.\n"
- " TARGET only determines which repository to access.\n"),
+ " TARGET only determines which repository to access.\n"
+ "\n"
+ " See 'svn help propset' for descriptions of the svn:* special properties.\n"),
{'q', 'R', opt_depth, 'r', opt_revprop, opt_changelist} },
{ "propedit", svn_cl__propedit, {"pedit", "pe"}, N_
@@ -1227,7 +1349,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" 2. Edits unversioned remote prop on repos revision.\n"
" TARGET only determines which repository to access.\n"
"\n"
- " See 'svn help propset' for more on setting properties.\n"),
+ " See 'svn help propset' for descriptions of the svn:* special properties.\n"),
{'r', opt_revprop, SVN_CL__LOG_MSG_OPTIONS, opt_force} },
{ "propget", svn_cl__propget, {"pget", "pg"}, N_
@@ -1246,13 +1368,15 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" 'empty', the target path is printed on the same line before each value.\n"
"\n"
" By default, an extra newline is printed after the property value so that\n"
- " the output looks pretty. With a single TARGET and depth 'empty', you can\n"
- " use the --strict option to disable this (useful when redirecting a binary\n"
- " property value to a file, for example).\n"),
- {'v', 'R', opt_depth, 'r', opt_revprop, opt_strict, opt_xml,
+ " the output looks pretty. With a single TARGET, depth 'empty' and without\n"
+ " --show-inherited-props, you can use the --no-newline option to disable this\n"
+ " (useful when redirecting a binary property value to a file, for example).\n"
+ "\n"
+ " See 'svn help propset' for descriptions of the svn:* special properties.\n"),
+ {'v', 'R', opt_depth, 'r', opt_revprop, opt_strict, opt_no_newline, opt_xml,
opt_changelist, opt_show_inherited_props },
{{'v', N_("print path, name and value on separate lines")},
- {opt_strict, N_("don't print an extra newline")}} },
+ {opt_strict, N_("(deprecated; use --no-newline)")}} },
{ "proplist", svn_cl__proplist, {"plist", "pl"}, N_
("List all properties on files, dirs, or revisions.\n"
@@ -1265,7 +1389,9 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" TARGET only determines which repository to access.\n"
"\n"
" With --verbose, the property values are printed as well, like 'svn propget\n"
- " --verbose'. With --quiet, the paths are not printed.\n"),
+ " --verbose'. With --quiet, the paths are not printed.\n"
+ "\n"
+ " See 'svn help propset' for descriptions of the svn:* special properties.\n"),
{'v', 'R', opt_depth, 'r', 'q', opt_revprop, opt_xml, opt_changelist,
opt_show_inherited_props },
{{'v', N_("print path, name and value on separate lines")},
@@ -1327,6 +1453,13 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" directory:\n"
" svn:ignore - A list of file glob patterns to ignore, one per line.\n"
" svn:global-ignores - Like svn:ignore, but inheritable.\n"
+ " svn:auto-props - Automatically set properties on files when they are\n"
+ " added or imported. Contains key-value pairs, one per line, in the format:\n"
+ " PATTERN = PROPNAME=VALUE[;PROPNAME=VALUE ...]\n"
+ " Example (where a literal ';' is escaped by adding another ';'):\n"
+ " *.html = svn:eol-style=native;svn:mime-type=text/html;; charset=UTF8\n"
+ " Applies recursively to all files added or imported under the directory\n"
+ " it is set on. See also [auto-props] in the client configuration file.\n"
" svn:externals - A list of module specifiers, one per line, in the\n"
" following format similar to the syntax of 'svn checkout':\n"
" [-r REV] URL[@PEG] LOCALPATH\n"
@@ -1343,6 +1476,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" ^/ to the repository root\n"
" / to the server root\n"
" // to the URL scheme\n"
+ " ^/../ to a sibling repository beneath the same SVNParentPath location\n"
" Use of the following format is discouraged but is supported for\n"
" interoperability with Subversion 1.4 and earlier clients:\n"
" LOCALPATH [-r PEG] URL\n"
@@ -1445,9 +1579,9 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" another Subversion client modifying the working copy\n"
" ' ' not locked for writing\n"
" 'L' locked for writing\n"
- " Fourth column: Scheduled commit will contain addition-with-history\n"
- " ' ' no history scheduled with commit\n"
- " '+' history scheduled with commit\n"
+ " Fourth column: Scheduled commit will create a copy (addition-with-history)\n"
+ " ' ' no history scheduled with commit (item was newly added)\n"
+ " '+' history scheduled with commit (item was copied)\n"
" Fifth column: Whether the item is switched or a file external\n"
" ' ' normal\n"
" 'S' the item has a Switched URL relative to the parent\n"
@@ -1507,8 +1641,8 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" ! C wc/qaz.c\n"
" > local missing, incoming edit upon update\n"
" D wc/qax.c\n"),
- { 'u', 'v', 'N', opt_depth, 'q', opt_no_ignore, opt_incremental, opt_xml,
- opt_ignore_externals, opt_changelist},
+ { 'u', 'v', 'N', opt_depth, 'r', 'q', opt_no_ignore, opt_incremental,
+ opt_xml, opt_ignore_externals, opt_changelist},
{{'q', N_("don't print unversioned items")}} },
{ "switch", svn_cl__switch, {"sw"}, N_
@@ -1554,7 +1688,9 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
{ 'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_relocate,
opt_ignore_externals, opt_ignore_ancestry, opt_force, opt_accept},
{{opt_ignore_ancestry,
- N_("allow switching to a node with no common ancestor")}}
+ N_("allow switching to a node with no common ancestor")},
+ {opt_force,
+ N_("handle unversioned obstructions as changes")}}
},
{ "unlock", svn_cl__unlock, {0}, N_
@@ -1612,7 +1748,9 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
" 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_force,
+ N_("handle unversioned obstructions as changes")} } },
{ "upgrade", svn_cl__upgrade, {0}, N_
("Upgrade the metadata storage format for a working copy.\n"
@@ -1660,6 +1798,8 @@ signal_handler(int signum)
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
@@ -1708,23 +1848,13 @@ add_search_pattern_to_latest_group(svn_cl__opt_state_t *opt_state,
/*** Main. ***/
-/* Report and clear the error ERR, and return EXIT_FAILURE. Suppress the
- * error message if it is SVN_ERR_IO_PIPE_WRITE_ERROR. */
-#define EXIT_ERROR(err) \
- svn_cmdline_handle_exit_error(err, NULL, "svn: ")
-
-/* A redefinition of the public SVN_INT_ERR macro, that suppresses the
- * error message if it is SVN_ERR_IO_PIPE_WRITE_ERROR. */
-#undef SVN_INT_ERR
-#define SVN_INT_ERR(expr) \
- do { \
- svn_error_t *svn_err__temp = (expr); \
- if (svn_err__temp) \
- return EXIT_ERROR(svn_err__temp); \
- } while (0)
-
-static int
-sub_main(int argc, const char *argv[], apr_pool_t *pool)
+/*
+ * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
+ * either return an error to be displayed, or set *EXIT_CODE to non-zero and
+ * return SVN_NO_ERROR.
+ */
+static svn_error_t *
+sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
{
svn_error_t *err;
int opt_id;
@@ -1734,7 +1864,7 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
apr_array_header_t *received_opts;
int i;
const svn_opt_subcommand_desc2_t *subcommand = NULL;
- const char *dash_m_arg = NULL, *dash_F_arg = NULL;
+ const char *dash_F_arg = NULL;
svn_cl__cmd_baton_t command_baton;
svn_auth_baton_t *ab;
svn_config_t *cfg_config;
@@ -1751,18 +1881,18 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
/* Check library versions */
- SVN_INT_ERR(check_lib_versions());
+ SVN_ERR(check_lib_versions());
#if defined(WIN32) || defined(__CYGWIN__)
/* Set the working copy administrative directory name. */
if (getenv("SVN_ASP_DOT_NET_HACK"))
{
- SVN_INT_ERR(svn_wc_set_adm_dir("_svn", pool));
+ SVN_ERR(svn_wc_set_adm_dir("_svn", pool));
}
#endif
/* Initialize the RA library. */
- SVN_INT_ERR(svn_ra_initialize(pool));
+ SVN_ERR(svn_ra_initialize(pool));
/* Init our changelists hash. */
changelists = apr_hash_make(pool);
@@ -1780,12 +1910,13 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
/* No args? Show usage. */
if (argc <= 1)
{
- SVN_INT_ERR(svn_cl__help(NULL, NULL, pool));
- return EXIT_FAILURE;
+ SVN_ERR(svn_cl__help(NULL, NULL, pool));
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
/* Else, parse options. */
- SVN_INT_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
+ SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
os->interleave = 1;
while (1)
@@ -1800,8 +1931,9 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
break;
else if (apr_err)
{
- SVN_INT_ERR(svn_cl__help(NULL, NULL, pool));
- return EXIT_FAILURE;
+ SVN_ERR(svn_cl__help(NULL, NULL, pool));
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
/* Stash the option code in an array before parsing it. */
@@ -1810,39 +1942,37 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
switch (opt_id) {
case 'l':
{
- err = svn_cstring_atoi(&opt_state.limit, opt_arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ err = svn_cstring_atoi(&opt_state.limit, utf8_opt_arg);
if (err)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, err,
- _("Non-numeric limit argument given"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+ _("Non-numeric limit argument given"));
}
if (opt_state.limit <= 0)
{
- err = svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
- _("Argument to --limit must be positive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+ _("Argument to --limit must be positive"));
}
}
break;
case 'm':
- /* Note that there's no way here to detect if the log message
- contains a zero byte -- if it does, then opt_arg will just
- be shorter than the user intended. Oh well. */
+ /* We store the raw message here. We will convert it to UTF-8
+ * later, according to the value of the '--encoding' option. */
opt_state.message = apr_pstrdup(pool, opt_arg);
- dash_m_arg = opt_arg;
break;
case 'c':
{
- apr_array_header_t *change_revs =
- svn_cstring_split(opt_arg, ", \n\r\t\v", TRUE, pool);
+ apr_array_header_t *change_revs;
+
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ change_revs = svn_cstring_split(utf8_opt_arg, ", \n\r\t\v", TRUE,
+ pool);
if (opt_state.old_target)
{
- err = svn_error_create
- (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Can't specify -c with --old"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Can't specify -c with --old"));
}
for (i = 0; i < change_revs->nelts; i++)
@@ -1870,12 +2000,11 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
{
if (changeno < 0 || is_negative)
{
- err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
- NULL,
- _("Negative number in range (%s)"
- " not supported with -c"),
- change_str);
- return EXIT_ERROR(err);
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+ NULL,
+ _("Negative number in range (%s)"
+ " not supported with -c"),
+ change_str);
}
s = end + 1;
while (*s == 'r')
@@ -1884,17 +2013,15 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
}
if (end == change_str || *end != '\0')
{
- err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Non-numeric change argument (%s) "
- "given to -c"), change_str);
- return EXIT_ERROR(err);
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Non-numeric change argument (%s) "
+ "given to -c"), change_str);
}
if (changeno == 0)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("There is no change 0"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("There is no change 0"));
}
if (is_negative)
@@ -1930,15 +2057,13 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
break;
case 'r':
opt_state.used_revision_arg = TRUE;
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
if (svn_opt_parse_revision_to_range(opt_state.revision_ranges,
- opt_arg, pool) != 0)
+ utf8_opt_arg, pool) != 0)
{
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
- err = svn_error_createf
- (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Syntax error in revision argument '%s'"),
utf8_opt_arg);
- return EXIT_ERROR(err);
}
break;
case 'v':
@@ -1958,23 +2083,22 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
opt_state.incremental = TRUE;
break;
case 'F':
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
- SVN_INT_ERR(svn_stringbuf_from_file2(&(opt_state.filedata),
- utf8_opt_arg, pool));
+ /* We read the raw file content here. We will convert it to UTF-8
+ * later (if it's a log/lock message or an svn:* prop value),
+ * according to the value of the '--encoding' option. */
+ 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));
reading_file_from_stdin = (strcmp(utf8_opt_arg, "-") == 0);
- dash_F_arg = opt_arg;
+ dash_F_arg = utf8_opt_arg;
break;
case opt_targets:
{
svn_stringbuf_t *buffer, *buffer_utf8;
- /* We need to convert to UTF-8 now, even before we divide
- the targets into an array, because otherwise we wouldn't
- know what delimiter to use for svn_cstring_split(). */
-
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
- SVN_INT_ERR(svn_stringbuf_from_file2(&buffer, utf8_opt_arg, pool));
- SVN_INT_ERR(svn_utf_stringbuf_to_utf8(&buffer_utf8, buffer, pool));
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ SVN_ERR(svn_stringbuf_from_file2(&buffer, utf8_opt_arg, pool));
+ SVN_ERR(svn_utf_stringbuf_to_utf8(&buffer_utf8, buffer, pool));
opt_state.targets = svn_cstring_split(buffer_utf8->data, "\n\r",
TRUE, pool);
}
@@ -2000,51 +2124,47 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
case opt_depth:
err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
if (err)
- return EXIT_ERROR
- (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
- _("Error converting depth "
- "from locale to UTF-8")));
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+ _("Error converting depth "
+ "from locale to UTF-8"));
opt_state.depth = svn_depth_from_word(utf8_opt_arg);
if (opt_state.depth == svn_depth_unknown
|| opt_state.depth == svn_depth_exclude)
{
- return EXIT_ERROR
- (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("'%s' is not a valid depth; try "
- "'empty', 'files', 'immediates', "
- "or 'infinity'"),
- utf8_opt_arg));
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid depth; try "
+ "'empty', 'files', 'immediates', "
+ "or 'infinity'"),
+ utf8_opt_arg);
}
break;
case opt_set_depth:
err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
if (err)
- return EXIT_ERROR
- (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
- _("Error converting depth "
- "from locale to UTF-8")));
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+ _("Error converting depth "
+ "from locale to UTF-8"));
opt_state.set_depth = svn_depth_from_word(utf8_opt_arg);
/* svn_depth_exclude is okay for --set-depth. */
if (opt_state.set_depth == svn_depth_unknown)
{
- return EXIT_ERROR
- (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("'%s' is not a valid depth; try "
- "'exclude', 'empty', 'files', "
- "'immediates', or 'infinity'"),
- utf8_opt_arg));
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid depth; try "
+ "'exclude', 'empty', 'files', "
+ "'immediates', or 'infinity'"),
+ utf8_opt_arg);
}
break;
case opt_version:
opt_state.version = TRUE;
break;
case opt_auth_username:
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_username,
- opt_arg, pool));
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_username,
+ opt_arg, pool));
break;
case opt_auth_password:
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password,
- opt_arg, pool));
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password,
+ opt_arg, pool));
break;
case opt_encoding:
opt_state.encoding = apr_pstrdup(pool, opt_arg);
@@ -2055,9 +2175,6 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
case opt_stop_on_copy:
opt_state.stop_on_copy = TRUE;
break;
- case opt_strict:
- opt_state.strict = TRUE;
- break;
case opt_no_ignore:
opt_state.no_ignore = TRUE;
break;
@@ -2070,8 +2187,18 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
case opt_force_interactive:
force_interactive = TRUE;
break;
- case opt_trust_server_cert:
- opt_state.trust_server_cert = TRUE;
+ case opt_trust_server_cert: /* backwards compat to 1.8 */
+ opt_state.trust_server_cert_unknown_ca = TRUE;
+ break;
+ case opt_trust_server_cert_failures:
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_trust_options(
+ &opt_state.trust_server_cert_unknown_ca,
+ &opt_state.trust_server_cert_cn_mismatch,
+ &opt_state.trust_server_cert_expired,
+ &opt_state.trust_server_cert_not_yet_valid,
+ &opt_state.trust_server_cert_other_failure,
+ utf8_opt_arg, pool));
break;
case opt_no_diff_added:
opt_state.diff.no_diff_added = TRUE;
@@ -2098,8 +2225,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
opt_state.relocate = TRUE;
break;
case 'x':
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.extensions,
- opt_arg, pool));
+ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.extensions,
+ opt_arg, pool));
break;
case opt_diff_cmd:
opt_state.diff.diff_cmd = apr_pstrdup(pool, opt_arg);
@@ -2116,22 +2243,19 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
case opt_old_cmd:
if (opt_state.used_change_arg)
{
- err = svn_error_create
- (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Can't specify -c with --old"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Can't specify -c with --old"));
}
- opt_state.old_target = apr_pstrdup(pool, opt_arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ opt_state.old_target = apr_pstrdup(pool, utf8_opt_arg);
break;
case opt_new_cmd:
- opt_state.new_target = apr_pstrdup(pool, opt_arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ opt_state.new_target = apr_pstrdup(pool, utf8_opt_arg);
break;
case opt_config_dir:
- {
- const char *path_utf8;
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&path_utf8, opt_arg, pool));
- opt_state.config_dir = svn_dirent_internal_style(path_utf8, pool);
- }
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ opt_state.config_dir = svn_dirent_internal_style(utf8_opt_arg, pool);
break;
case opt_config_options:
if (!opt_state.config_options)
@@ -2139,9 +2263,9 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
apr_array_make(pool, 1,
sizeof(svn_cmdline__config_argument_t*));
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
- SVN_INT_ERR(svn_cmdline__parse_config_option(opt_state.config_options,
- opt_arg, pool));
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ SVN_ERR(svn_cmdline__parse_config_option(opt_state.config_options,
+ utf8_opt_arg, "svn: ", pool));
break;
case opt_autoprops:
opt_state.autoprops = TRUE;
@@ -2150,17 +2274,15 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
opt_state.no_autoprops = TRUE;
break;
case opt_native_eol:
- if ( !strcmp("LF", opt_arg) || !strcmp("CR", opt_arg) ||
- !strcmp("CRLF", opt_arg))
- opt_state.native_eol = apr_pstrdup(pool, opt_arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ if ( !strcmp("LF", utf8_opt_arg) || !strcmp("CR", utf8_opt_arg) ||
+ !strcmp("CRLF", utf8_opt_arg))
+ opt_state.native_eol = utf8_opt_arg;
else
{
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
- err = svn_error_createf
- (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Syntax error in native-eol argument '%s'"),
utf8_opt_arg);
- return EXIT_ERROR(err);
}
break;
case opt_no_unlock:
@@ -2173,15 +2295,13 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
opt_state.remove = TRUE;
break;
case opt_changelist:
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
- opt_state.changelist = utf8_opt_arg;
- if (opt_state.changelist[0] == '\0')
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ if (utf8_opt_arg[0] == '\0')
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Changelist names must not be empty"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Changelist names must not be empty"));
}
- svn_hash_sets(changelists, opt_state.changelist, (void *)1);
+ svn_hash_sets(changelists, utf8_opt_arg, (void *)1);
break;
case opt_keep_changelists:
opt_state.keep_changelists = TRUE;
@@ -2198,8 +2318,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
opt_state.no_revprops = TRUE;
break;
case opt_with_revprop:
- SVN_INT_ERR(svn_opt_parse_revprop(&opt_state.revprop_table,
- opt_arg, pool));
+ SVN_ERR(svn_opt_parse_revprop(&opt_state.revprop_table,
+ opt_arg, pool));
break;
case opt_parents:
opt_state.parents = TRUE;
@@ -2208,38 +2328,41 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
opt_state.use_merge_history = TRUE;
break;
case opt_accept:
- opt_state.accept_which = svn_cl__accept_from_word(opt_arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ opt_state.accept_which = svn_cl__accept_from_word(utf8_opt_arg);
if (opt_state.accept_which == svn_cl__accept_invalid)
- return EXIT_ERROR
- (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("'%s' is not a valid --accept value"),
- opt_arg));
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid --accept value"),
+ utf8_opt_arg);
break;
case opt_show_revs:
- opt_state.show_revs = svn_cl__show_revs_from_word(opt_arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ opt_state.show_revs = svn_cl__show_revs_from_word(utf8_opt_arg);
if (opt_state.show_revs == svn_cl__show_revs_invalid)
- return EXIT_ERROR
- (svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("'%s' is not a valid --show-revs value"),
- opt_arg));
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("'%s' is not a valid --show-revs value"),
+ utf8_opt_arg);
+ break;
+ case opt_mergeinfo_log:
+ opt_state.mergeinfo_log = TRUE;
break;
case opt_reintegrate:
opt_state.reintegrate = TRUE;
break;
case opt_strip:
{
- err = svn_cstring_atoi(&opt_state.strip, opt_arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ err = svn_cstring_atoi(&opt_state.strip, utf8_opt_arg);
if (err)
{
- err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
- _("Invalid strip count '%s'"), opt_arg);
- return EXIT_ERROR(err);
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
+ _("Invalid strip count '%s'"),
+ utf8_opt_arg);
}
if (opt_state.strip < 0)
{
- err = svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
- _("Argument to --strip must be positive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+ _("Argument to --strip must be positive"));
}
}
break;
@@ -2277,10 +2400,32 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
opt_state.diff.properties_only = TRUE;
break;
case opt_search:
- add_search_pattern_group(&opt_state, opt_arg, pool);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ add_search_pattern_group(&opt_state, utf8_opt_arg, pool);
break;
case opt_search_and:
- add_search_pattern_to_latest_group(&opt_state, opt_arg, pool);
+ 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);
+ case opt_remove_unversioned:
+ opt_state.remove_unversioned = TRUE;
+ break;
+ case opt_remove_ignored:
+ opt_state.remove_ignored = TRUE;
+ break;
+ case opt_no_newline:
+ case opt_strict: /* ### DEPRECATED */
+ opt_state.no_newline = TRUE;
+ break;
+ case opt_show_passwords:
+ opt_state.show_passwords = TRUE;
+ break;
+ case opt_pin_externals:
+ opt_state.pin_externals = TRUE;
+ break;
+ case opt_show_item:
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+ opt_state.show_item = utf8_opt_arg;
+ break;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
@@ -2292,10 +2437,9 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
* exclusive. */
if (opt_state.non_interactive && force_interactive)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--non-interactive and --force-interactive "
- "are mutually exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--non-interactive and --force-interactive "
+ "are mutually exclusive"));
}
else
opt_state.non_interactive = !svn_cmdline__be_interactive(
@@ -2303,7 +2447,7 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
force_interactive);
/* Turn our hash of changelists into an array of unique ones. */
- SVN_INT_ERR(svn_hash_keys(&(opt_state.changelists), changelists, pool));
+ SVN_ERR(svn_hash_keys(&(opt_state.changelists), changelists, pool));
/* ### This really belongs in libsvn_client. The trouble is,
there's no one place there to run it from, no
@@ -2315,7 +2459,7 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
hand, the alternative is effectively to demand that they call
svn_config_ensure() instead, so maybe we should have a generic
init function anyway. Thoughts? */
- SVN_INT_ERR(svn_config_ensure(opt_state.config_dir, pool));
+ SVN_ERR(svn_config_ensure(opt_state.config_dir, pool));
/* If the user asked for help, then the rest of the arguments are
the names of subcommands to get help on (if any), or else they're
@@ -2349,7 +2493,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
(svn_cmdline_fprintf(stderr, pool,
_("Subcommand argument required\n")));
svn_error_clear(svn_cl__help(NULL, NULL, pool));
- return EXIT_FAILURE;
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
}
else
@@ -2360,8 +2505,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
if (subcommand == NULL)
{
const char *first_arg_utf8;
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8,
- first_arg, pool));
+ SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8,
+ first_arg, pool));
svn_error_clear
(svn_cmdline_fprintf(stderr, pool,
_("Unknown subcommand: '%s'\n"),
@@ -2378,7 +2523,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
"command.\n")));
}
- return EXIT_FAILURE;
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
}
}
@@ -2411,7 +2557,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
(stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n"
"Type 'svn help %s' for usage.\n"),
subcommand->name, optstr, subcommand->name));
- return EXIT_FAILURE;
+ *exit_code = EXIT_FAILURE;
+ return SVN_NO_ERROR;
}
}
@@ -2421,11 +2568,10 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
{
if (opt_state.revision_ranges->nelts > 1)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Multiple revision arguments "
- "encountered; can't specify -c twice, "
- "or both -c and -r"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Multiple revision arguments "
+ "encountered; can't specify -c twice, "
+ "or both -c and -r"));
}
}
@@ -2433,32 +2579,47 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
if ((opt_state.depth != svn_depth_unknown)
&& (opt_state.set_depth != svn_depth_unknown))
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--depth and --set-depth are mutually "
- "exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--depth and --set-depth are mutually "
+ "exclusive"));
}
/* Disallow simultaneous use of both --with-all-revprops and
--with-no-revprops. */
if (opt_state.all_revprops && opt_state.no_revprops)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--with-all-revprops and --with-no-revprops "
- "are mutually exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--with-all-revprops and --with-no-revprops "
+ "are mutually exclusive"));
}
/* Disallow simultaneous use of both --with-revprop and
--with-no-revprops. */
if (opt_state.revprop_table && opt_state.no_revprops)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--with-revprop and --with-no-revprops "
- "are mutually exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--with-revprop and --with-no-revprops "
+ "are mutually exclusive"));
}
+#ifdef SVN_CL__OPTION_WITH_REVPROP_CAN_SET_PROPERTIES_IN_SVN_NAMESPACE
+ /* XXX This is incomplete, since we do not yet check for --force, nor
+ do all the commands that accept --with-revprop also accept --force. */
+
+ /* Check the spelling of the revision properties given by --with-revprop. */
+ if (opt_state.revprop_table)
+ {
+ apr_hash_index_t *hi;
+ for (hi = apr_hash_first(pool, opt_state.revprop_table);
+ hi; hi = apr_hash_next(hi))
+ {
+ SVN_ERR(svn_cl__check_svn_prop_name(apr_hash_this_key(hi),
+ TRUE, svn_cl__prop_use_use,
+ pool));
+ }
+ }
+#endif /* SVN_CL__OPTION_WITH_REVPROP_CAN_SET_PROPERTIES_IN_SVN_NAMESPACE */
+
/* Disallow simultaneous use of both -m and -F, when they are
both used to pass a commit message or lock comment. ('propset'
takes the property value, not a commit message, from -F.)
@@ -2466,29 +2627,31 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
if (opt_state.filedata && opt_state.message
&& subcommand->cmd_func != svn_cl__propset)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--message (-m) and --file (-F) "
- "are mutually exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--message (-m) and --file (-F) "
+ "are mutually exclusive"));
}
- /* --trust-server-cert can only be used with --non-interactive */
- if (opt_state.trust_server_cert && !opt_state.non_interactive)
+ /* --trust-* options can only be used with --non-interactive */
+ if (!opt_state.non_interactive)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--trust-server-cert requires "
- "--non-interactive"));
- return EXIT_ERROR(err);
+ if (opt_state.trust_server_cert_unknown_ca
+ || opt_state.trust_server_cert_cn_mismatch
+ || opt_state.trust_server_cert_expired
+ || opt_state.trust_server_cert_not_yet_valid
+ || opt_state.trust_server_cert_other_failure)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--trust-server-cert-failures requires "
+ "--non-interactive"));
}
/* Disallow simultaneous use of both --diff-cmd and
--internal-diff. */
if (opt_state.diff.diff_cmd && opt_state.diff.internal_diff)
{
- err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("--diff-cmd and --internal-diff "
- "are mutually exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--diff-cmd and --internal-diff "
+ "are mutually exclusive"));
}
/* Ensure that 'revision_ranges' has at least one item, and make
@@ -2514,18 +2677,13 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
if (APR_STATUS_IS_EACCES(err->apr_err)
|| SVN__APR_STATUS_IS_ENOTDIR(err->apr_err))
{
- svn_config_t *empty_cfg;
-
svn_handle_warning2(stderr, err, "svn: ");
svn_error_clear(err);
- cfg_hash = apr_hash_make(pool);
- SVN_INT_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool));
- svn_hash_sets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, empty_cfg);
- SVN_INT_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool));
- svn_hash_sets(cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, empty_cfg);
+
+ SVN_ERR(svn_config__get_default_config(&cfg_hash, pool));
}
else
- return EXIT_ERROR(err);
+ return err;
}
/* Relocation is infinite-depth only. */
@@ -2533,18 +2691,16 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
{
if (opt_state.depth != svn_depth_unknown)
{
- err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
- _("--relocate and --depth are mutually "
- "exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+ _("--relocate and --depth are mutually "
+ "exclusive"));
}
if (! descend)
{
- err = svn_error_create(
+ return svn_error_create(
SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
_("--relocate and --non-recursive (-N) are mutually "
"exclusive"));
- return EXIT_ERROR(err);
}
}
@@ -2558,8 +2714,7 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
{
if (opt_state.end_revision.kind != svn_opt_revision_unspecified)
{
- err = svn_error_create(SVN_ERR_CLIENT_REVISION_RANGE, NULL, NULL);
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CLIENT_REVISION_RANGE, NULL, NULL);
}
}
@@ -2586,8 +2741,6 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
}
}
- cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG);
-
/* Update the options in the config */
if (opt_state.config_options)
{
@@ -2597,6 +2750,7 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
"svn: ", "--config-option"));
}
+ cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG);
#if !defined(SVN_CL_NO_EXCLUSIVE_LOCK)
{
const char *exclusive_clients_option;
@@ -2626,7 +2780,7 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
/* Create a client context object. */
command_baton.opt_state = &opt_state;
- SVN_INT_ERR(svn_client_create_context2(&ctx, cfg_hash, pool));
+ SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool));
command_baton.ctx = ctx;
/* If we're running a command that could result in a commit, verify
@@ -2662,19 +2816,18 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
{
if (subcommand->cmd_func != svn_cl__lock)
{
- err = svn_error_create(
+ return svn_error_create(
SVN_ERR_CL_LOG_MESSAGE_IS_VERSIONED_FILE, NULL,
_("Log message file is a versioned file; "
"use '--force-log' to override"));
}
else
{
- err = svn_error_create(
+ return svn_error_create(
SVN_ERR_CL_LOG_MESSAGE_IS_VERSIONED_FILE, NULL,
_("Lock comment file is a versioned file; "
"use '--force-log' to override"));
}
- return EXIT_ERROR(err);
}
}
svn_error_clear(err);
@@ -2682,27 +2835,26 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
/* If the -m argument is a file at all, that's probably not what
the user intended. */
- if (dash_m_arg)
+ if (opt_state.message)
{
apr_finfo_t finfo;
- if (apr_stat(&finfo, dash_m_arg,
+ if (apr_stat(&finfo, opt_state.message /* not converted to UTF-8 */,
APR_FINFO_MIN, pool) == APR_SUCCESS)
{
if (subcommand->cmd_func != svn_cl__lock)
{
- err = svn_error_create
+ return svn_error_create
(SVN_ERR_CL_LOG_MESSAGE_IS_PATHNAME, NULL,
_("The log message is a pathname "
"(was -F intended?); use '--force-log' to override"));
}
else
{
- err = svn_error_create
+ return svn_error_create
(SVN_ERR_CL_LOG_MESSAGE_IS_PATHNAME, NULL,
_("The lock comment is a pathname "
"(was -F intended?); use '--force-log' to override"));
}
- return EXIT_ERROR(err);
}
}
}
@@ -2722,10 +2874,9 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
/* Check for mutually exclusive args --auto-props and --no-auto-props */
if (opt_state.autoprops && opt_state.no_autoprops)
{
- err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
- _("--auto-props and --no-auto-props are "
- "mutually exclusive"));
- return EXIT_ERROR(err);
+ return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+ _("--auto-props and --no-auto-props are "
+ "mutually exclusive"));
}
/* Update auto-props-enable option, and populate the MIME types map,
@@ -2739,8 +2890,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
SVN_CONFIG_OPTION_MIMETYPES_FILE, FALSE);
if (mimetypes_file && *mimetypes_file)
{
- SVN_INT_ERR(svn_io_parse_mimetypes_file(&(ctx->mimetypes_map),
- mimetypes_file, pool));
+ SVN_ERR(svn_io_parse_mimetypes_file(&(ctx->mimetypes_map),
+ mimetypes_file, pool));
}
if (opt_state.autoprops)
@@ -2778,8 +2929,8 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
use_notifier = FALSE;
if (use_notifier)
{
- SVN_INT_ERR(svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2,
- conflict_stats, pool));
+ SVN_ERR(svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2,
+ conflict_stats, pool));
}
/* Set up our cancellation support. */
@@ -2809,35 +2960,41 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
#endif
/* Set up Authentication stuff. */
- SVN_INT_ERR(svn_cmdline_create_auth_baton(&ab,
- opt_state.non_interactive,
- opt_state.auth_username,
- opt_state.auth_password,
- opt_state.config_dir,
- opt_state.no_auth_cache,
- opt_state.trust_server_cert,
- cfg_config,
- ctx->cancel_func,
- ctx->cancel_baton,
- pool));
+ SVN_ERR(svn_cmdline_create_auth_baton2(
+ &ab,
+ opt_state.non_interactive,
+ opt_state.auth_username,
+ opt_state.auth_password,
+ opt_state.config_dir,
+ opt_state.no_auth_cache,
+ opt_state.trust_server_cert_unknown_ca,
+ opt_state.trust_server_cert_cn_mismatch,
+ opt_state.trust_server_cert_expired,
+ opt_state.trust_server_cert_not_yet_valid,
+ opt_state.trust_server_cert_other_failure,
+ cfg_config,
+ ctx->cancel_func,
+ ctx->cancel_baton,
+ pool));
ctx->auth_baton = ab;
if (opt_state.non_interactive)
{
if (opt_state.accept_which == svn_cl__accept_edit)
- return EXIT_ERROR(
- svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ {
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("--accept=%s incompatible with"
" --non-interactive"),
- SVN_CL__ACCEPT_EDIT));
-
+ SVN_CL__ACCEPT_EDIT);
+ }
if (opt_state.accept_which == svn_cl__accept_launch)
- return EXIT_ERROR(
- svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ {
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("--accept=%s incompatible with"
" --non-interactive"),
- SVN_CL__ACCEPT_LAUNCH));
+ SVN_CL__ACCEPT_LAUNCH);
+ }
/* The default action when we're non-interactive is to postpone
* conflict resolution. */
@@ -2848,10 +3005,10 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
/* Check whether interactive conflict resolution is disabled by
* the configuration file. If no --accept option was specified
* we postpone all conflicts in this case. */
- SVN_INT_ERR(svn_config_get_bool(cfg_config, &interactive_conflicts,
- SVN_CONFIG_SECTION_MISCELLANY,
- SVN_CONFIG_OPTION_INTERACTIVE_CONFLICTS,
- TRUE));
+ SVN_ERR(svn_config_get_bool(cfg_config, &interactive_conflicts,
+ SVN_CONFIG_SECTION_MISCELLANY,
+ SVN_CONFIG_OPTION_INTERACTIVE_CONFLICTS,
+ TRUE));
if (!interactive_conflicts)
{
/* Make 'svn resolve' non-interactive. */
@@ -2872,7 +3029,7 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
ctx->conflict_baton = NULL;
ctx->conflict_func2 = svn_cl__conflict_func_interactive;
- SVN_INT_ERR(svn_cl__get_conflict_func_interactive_baton(
+ SVN_ERR(svn_cl__get_conflict_func_interactive_baton(
&b,
opt_state.accept_which,
ctx->config, opt_state.editor_cmd, conflict_stats,
@@ -2889,10 +3046,9 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
if (err->apr_err == SVN_ERR_CL_INSUFFICIENT_ARGS
|| err->apr_err == SVN_ERR_CL_ARG_PARSING_ERROR)
{
- err = svn_error_quick_wrap(
- err, apr_psprintf(pool,
- _("Try 'svn help %s' for more information"),
- subcommand->name));
+ err = svn_error_quick_wrapf(
+ err, _("Try 'svn help %s' for more information"),
+ subcommand->name);
}
if (err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
{
@@ -2945,27 +3101,18 @@ sub_main(int argc, const char *argv[], apr_pool_t *pool)
"Subversion"));
}
- /* Ensure that stdout is flushed, so the user will see any write errors.
- This makes sure that output is not silently lost. */
- err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
-
- return EXIT_ERROR(err);
+ return err;
}
- else
- {
- /* Ensure that stdout is flushed, so the user will see any write errors.
- This makes sure that output is not silently lost. */
- SVN_INT_ERR(svn_cmdline_fflush(stdout));
- return EXIT_SUCCESS;
- }
+ return SVN_NO_ERROR;
}
int
main(int argc, const char *argv[])
{
apr_pool_t *pool;
- int exit_code;
+ int exit_code = EXIT_SUCCESS;
+ svn_error_t *err;
/* Initialize the app. */
if (svn_cmdline_init("svn", stderr) != EXIT_SUCCESS)
@@ -2976,7 +3123,17 @@ main(int argc, const char *argv[])
*/
pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
- exit_code = sub_main(argc, argv, pool);
+ err = sub_main(&exit_code, argc, argv, pool);
+
+ /* Flush stdout and report if it fails. It would be flushed on exit anyway
+ but this makes sure that output is not silently lost if it fails. */
+ err = svn_error_compose_create(err, svn_cmdline_fflush(stdout));
+
+ if (err)
+ {
+ exit_code = EXIT_FAILURE;
+ svn_cmdline_handle_exit_error(err, NULL, "svn: ");
+ }
svn_pool_destroy(pool);
return exit_code;