📄 main.c
字号:
/* Version compatibility check */
static svn_error_t *
check_lib_versions (void)
{
static const svn_version_checklist_t checklist[] =
{
{ "svn_subr", svn_subr_version },
{ "svn_client", svn_client_version },
{ "svn_wc", svn_wc_version },
{ "svn_ra", svn_ra_version },
{ "svn_delta", svn_delta_version },
{ NULL, NULL }
};
SVN_VERSION_DEFINE (my_version);
return svn_ver_check_list (&my_version, checklist);
}
/* A flag to see if we've been cancelled by the client or not. */
static volatile sig_atomic_t cancelled = FALSE;
/* A signal handler to support cancellation. */
static void
signal_handler (int signum)
{
apr_signal (signum, SIG_IGN);
cancelled = TRUE;
}
/* Our cancellation callback. */
svn_error_t *
svn_cl__check_cancel (void *baton)
{
if (cancelled)
return svn_error_create (SVN_ERR_CANCELLED, NULL, _("Caught signal"));
else
return SVN_NO_ERROR;
}
/*** Main. ***/
int
main (int argc, const char * const *argv)
{
svn_error_t *err;
apr_allocator_t *allocator;
apr_pool_t *pool;
int opt_id;
apr_getopt_t *os;
svn_cl__opt_state_t opt_state = { { 0 } };
svn_client_ctx_t *ctx;
int received_opts[SVN_OPT_MAX_OPTIONS];
int i, num_opts = 0;
const svn_opt_subcommand_desc_t *subcommand = NULL;
const char *dash_m_arg = NULL, *dash_F_arg = NULL;
const char *path_utf8;
apr_status_t apr_err;
svn_cl__cmd_baton_t command_baton;
svn_auth_baton_t *ab;
svn_config_t *cfg;
/* Initialize the app. */
if (svn_cmdline_init ("svn", stderr) != EXIT_SUCCESS)
return EXIT_FAILURE;
/* Create our top-level pool. Use a seperate mutexless allocator,
* given this application is single threaded.
*/
if (apr_allocator_create (&allocator))
return EXIT_FAILURE;
apr_allocator_max_free_set (allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
pool = svn_pool_create_ex (NULL, allocator);
apr_allocator_owner_set (allocator, pool);
/* Check library versions */
err = check_lib_versions ();
if (err)
return error_exit (err, stderr, FALSE, pool);
/* Begin processing arguments. */
opt_state.start_revision.kind = svn_opt_revision_unspecified;
opt_state.end_revision.kind = svn_opt_revision_unspecified;
/* No args? Show usage. */
if (argc <= 1)
{
svn_cl__help (NULL, NULL, pool);
svn_pool_destroy (pool);
return EXIT_FAILURE;
}
/* Else, parse options. */
apr_getopt_init (&os, pool, argc, argv);
os->interleave = 1;
while (1)
{
const char *opt_arg;
const char *utf8_opt_arg;
/* Parse the next option. */
apr_err = apr_getopt_long (os, svn_cl__options, &opt_id, &opt_arg);
if (APR_STATUS_IS_EOF (apr_err))
break;
else if (apr_err)
{
svn_cl__help (NULL, NULL, pool);
svn_pool_destroy (pool);
return EXIT_FAILURE;
}
/* Stash the option code in an array before parsing it. */
received_opts[num_opts] = opt_id;
num_opts++;
switch (opt_id) {
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. */
opt_state.message = apr_pstrdup (pool, opt_arg);
dash_m_arg = opt_arg;
break;
case 'r':
if (opt_state.start_revision.kind != svn_opt_revision_unspecified)
{
err = svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Multiple revision arguments encountered; "
"try '-r M:N' instead of '-r M -r N'"));
return error_exit (err, stderr, FALSE, pool);
}
if (svn_opt_parse_revision (&(opt_state.start_revision),
&(opt_state.end_revision),
opt_arg, pool) != 0)
{
err = svn_utf_cstring_to_utf8 (&utf8_opt_arg, opt_arg, pool);
if (! err)
err = svn_error_createf
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Syntax error in revision argument '%s'"),
utf8_opt_arg);
return error_exit (err, stderr, FALSE, pool);
}
break;
case 'v':
opt_state.verbose = TRUE;
break;
case 'u':
opt_state.update = TRUE;
break;
case 'h':
case '?':
opt_state.help = TRUE;
break;
case 'q':
opt_state.quiet = TRUE;
break;
case svn_cl__incremental_opt:
opt_state.incremental = TRUE;
break;
case 'F':
err = svn_utf_cstring_to_utf8 (&utf8_opt_arg, opt_arg, pool);
if (! err)
err = svn_stringbuf_from_file (&(opt_state.filedata),
utf8_opt_arg, pool);
if (err)
return error_exit (err, stderr, FALSE, pool);
dash_F_arg = opt_arg;
break;
case svn_cl__targets_opt:
{
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(). */
err = svn_utf_cstring_to_utf8 (&utf8_opt_arg, opt_arg, pool);
if (! err)
err = svn_stringbuf_from_file (&buffer, utf8_opt_arg, pool);
if (! err)
err = svn_utf_stringbuf_to_utf8 (&buffer_utf8, buffer, pool);
if (err)
return error_exit (err, stdout, FALSE, pool);
opt_state.targets = svn_cstring_split (buffer_utf8->data, "\n\r",
TRUE, pool);
}
break;
case svn_cl__force_opt:
opt_state.force = TRUE;
break;
case svn_cl__force_log_opt:
opt_state.force_log = TRUE;
break;
case svn_cl__dry_run_opt:
opt_state.dry_run = TRUE;
break;
case svn_cl__revprop_opt:
opt_state.revprop = TRUE;
break;
case 'R':
opt_state.recursive = TRUE;
break;
case 'N':
opt_state.nonrecursive = TRUE;
break;
case svn_cl__version_opt:
opt_state.version = TRUE;
opt_state.help = TRUE;
break;
case svn_cl__auth_username_opt:
err = svn_utf_cstring_to_utf8 (&opt_state.auth_username,
opt_arg, pool);
if (err)
return error_exit (err, stdout, FALSE, pool);
break;
case svn_cl__auth_password_opt:
err = svn_utf_cstring_to_utf8 (&opt_state.auth_password,
opt_arg, pool);
if (err)
return error_exit (err, stdout, FALSE, pool);
break;
case svn_cl__encoding_opt:
opt_state.encoding = apr_pstrdup (pool, opt_arg);
break;
case svn_cl__xml_opt:
opt_state.xml = TRUE;
break;
case svn_cl__stop_on_copy_opt:
opt_state.stop_on_copy = TRUE;
break;
case svn_cl__strict_opt:
opt_state.strict = TRUE;
break;
case svn_cl__no_ignore_opt:
opt_state.no_ignore = TRUE;
break;
case svn_cl__no_auth_cache_opt:
opt_state.no_auth_cache = TRUE;
break;
case svn_cl__non_interactive_opt:
opt_state.non_interactive = TRUE;
break;
case svn_cl__no_diff_deleted:
opt_state.no_diff_deleted = TRUE;
break;
case svn_cl__notice_ancestry_opt:
opt_state.notice_ancestry = TRUE;
break;
case svn_cl__ignore_ancestry_opt:
opt_state.ignore_ancestry = TRUE;
break;
case svn_cl__relocate_opt:
opt_state.relocate = TRUE;
break;
case 'x':
err = svn_utf_cstring_to_utf8 (&opt_state.extensions, opt_arg, pool);
if (err)
return error_exit (err, stderr, FALSE, pool);
break;
case svn_cl__diff_cmd_opt:
opt_state.diff_cmd = apr_pstrdup (pool, opt_arg);
break;
case svn_cl__merge_cmd_opt:
opt_state.merge_cmd = apr_pstrdup (pool, opt_arg);
break;
case svn_cl__editor_cmd_opt:
opt_state.editor_cmd = apr_pstrdup (pool, opt_arg);
break;
case svn_cl__old_cmd_opt:
opt_state.old_target = apr_pstrdup (pool, opt_arg);
break;
case svn_cl__new_cmd_opt:
opt_state.new_target = apr_pstrdup (pool, opt_arg);
break;
case svn_cl__config_dir_opt:
err = svn_utf_cstring_to_utf8 (&path_utf8, opt_arg, pool);
opt_state.config_dir = svn_path_canonicalize (path_utf8, pool);
break;
case svn_cl__autoprops_opt:
if (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 error_exit (err, stderr, FALSE, pool);
}
opt_state.autoprops = TRUE;
break;
case svn_cl__no_autoprops_opt:
if (opt_state.autoprops)
{
err = svn_error_create (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
_("--auto-props and --no-auto-props are "
"mutually exclusive"));
return error_exit (err, stderr, FALSE, pool);
}
opt_state.no_autoprops = TRUE;
break;
case svn_cl__native_eol_opt:
if ( !strcmp ("LF", opt_arg) || !strcmp ("CR", opt_arg) ||
!strcmp ("CRLF", opt_arg))
opt_state.native_eol = apr_pstrdup (pool, opt_arg);
else
{
err = svn_utf_cstring_to_utf8 (&utf8_opt_arg, opt_arg, pool);
if (! err)
err = svn_error_createf
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Syntax error in native-eol argument '%s'"),
utf8_opt_arg);
svn_handle_error (err, stderr, FALSE);
svn_error_clear (err);
svn_pool_destroy (pool);
return EXIT_FAILURE;
}
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
break;
}
}
/* ### This really belongs in libsvn_client. The trouble is,
there's no one place there to run it from, no
svn_client_init(). We'd have to add it to all the public
functions that a client might call. It's unmaintainable to do
initialization from within libsvn_client itself, but it seems
burdensome to demand that all clients call svn_client_init()
before calling any other libsvn_client function... On the other
hand, the alternative is effective to demand that they call
svn_config_ensure() instead, so maybe we should have a generic
init function anyway. Thoughts? */
err = svn_config_ensure (opt_state.config_dir, pool);
if (err)
return error_exit (err, stderr, FALSE, pool);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -