static void help(apr_pool_t *pool) { apr_size_t i; #ifdef WIN32 svn_error_clear(svn_cmdline_fputs(_("usage: svnserve [-d | -i | -t | -X " "| --service] [options]\n" "Subversion repository server.\n" "Type 'svnserve --version' to see the " "program version.\n" "\n" "Valid options:\n"), stdout, pool)); #else svn_error_clear(svn_cmdline_fputs(_("usage: svnserve [-d | -i | -t | -X] " "[options]\n" "Subversion repository server.\n" "Type 'svnserve --version' to see the " "program version.\n" "\n" "Valid options:\n"), stdout, pool)); #endif for (i = 0; svnserve__options[i].name && svnserve__options[i].optch; i++) { const char *optstr; svn_opt_format_option(&optstr, svnserve__options + i, TRUE, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, " %s\n", optstr)); } svn_error_clear(svn_cmdline_fprintf(stdout, pool, "\n")); }
static void help(const apr_getopt_option_t *options, apr_pool_t *pool) { svn_error_clear (svn_cmdline_fprintf (stdout, pool, _("usage: svnraisetreeconflict [OPTIONS] WC_PATH NODE_KIND OPERATION ACTION REASON REPOS_URL1 PATH_IN_REPOS1 PEG_REV1 NODE_KIND1 REPOS_URL2 PATH_IN_REPOS2 PEG_REV2 NODE_KIND2\n\n" " Mark the working-copy node WC_PATH as being the victim of a tree conflict.\n" "\n" " WC_PATH's parent directory must be a working copy, otherwise a\n" " tree conflict cannot be raised.\n" "\n" "Valid options:\n"))); while (options->description) { const char *optstr; svn_opt_format_option(&optstr, options, TRUE, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, " %s\n", optstr)); ++options; } svn_error_clear(svn_cmdline_fprintf(stdout, pool, _("\n" "Valid enum argument values:\n" " NODE_KIND, NODE_KIND1, NODE_KIND2:\n" " "))); print_enum_map(node_kind_map, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, _("\n" " OPERATION:\n" " "))); print_enum_map(operation_map, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, _("\n" " ACTION (what svn tried to do):\n" " "))); print_enum_map(action_map, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, _("\n" " REASON (what local change made svn fail):\n" " "))); print_enum_map(reason_map, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, _("\n" " REPOS_URL1, REPOS_URL2:\n" " The URL of the repository itself, e.g.: file://usr/repos\n" " PATH_IN_REPOS1, PATH_IN_REPOS2:\n" " The complete path of the node in the repository, e.g.: sub/dir/foo\n" " PEG_REV1, PEG_REV2:\n" " The revision number at which the given path is relevant.\n" "\n" "Example:\n" " svnraisetreeconflict ./foo %s %s %s %s file://usr/repos sub/dir/foo 1 %s file://usr/repos sub/dir/foo 3 %s\n\n"), get_enum_str(node_kind_map, svn_node_file), get_enum_str(operation_map, svn_wc_operation_update), get_enum_str(action_map, svn_wc_conflict_action_delete), get_enum_str(reason_map, svn_wc_conflict_reason_deleted), get_enum_str(node_kind_map, svn_node_file), get_enum_str(node_kind_map, svn_node_none) )); }
static void help(const apr_getopt_option_t *options, apr_pool_t *pool) { svn_error_clear (svn_cmdline_fprintf (stdout, pool, _("usage: svnversion [OPTIONS] [WC_PATH [TRAIL_URL]]\n" "Subversion working copy identification tool.\n" "Type 'svnversion --version' to see the program version.\n" "\n" " Produce a compact version identifier for the working copy path\n" " WC_PATH. TRAIL_URL is the trailing portion of the URL used to\n" " determine if WC_PATH itself is switched (detection of switches\n" " within WC_PATH does not rely on TRAIL_URL). The version identifier\n" " is written to standard output. For example:\n" "\n" " $ svnversion . /repos/svn/trunk\n" " 4168\n" "\n" " The version identifier will be a single number if the working\n" " copy is single revision, unmodified, not switched and with\n" " a URL that matches the TRAIL_URL argument. If the working\n" " copy is unusual the version identifier will be more complex:\n" "\n" " 4123:4168 mixed revision working copy\n" " 4168M modified working copy\n" " 4123S switched working copy\n" " 4123P partial working copy, from a sparse checkout\n" " 4123:4168MS mixed revision, modified, switched working copy\n" "\n" " If WC_PATH is an unversioned path, the program will output\n" " 'Unversioned directory' or 'Unversioned file'. If WC_PATH is\n" " an added or copied or moved path, the program will output\n" " 'Uncommitted local addition, copy or move'.\n" "\n" " If invoked without arguments WC_PATH will be the current directory.\n" "\n" "Valid options:\n"))); while (options->description) { const char *optstr; svn_opt_format_option(&optstr, options, TRUE, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, " %s\n", optstr)); ++options; } svn_error_clear(svn_cmdline_fprintf(stdout, pool, "\n")); }
static void help(const apr_getopt_option_t *options, apr_pool_t *pool) { svn_error_clear (svn_cmdline_fprintf (stdout, pool, _("usage: svn-wc-db-tester [OPTIONS] WC_PATH\n\n" " Run verifications on the working copy\n" "\n" " WC_PATH's parent directory must be a working copy, otherwise a\n" " tree conflict cannot be raised.\n" "\n" "Valid options:\n"))); while (options->description) { const char *optstr; svn_opt_format_option(&optstr, options, TRUE, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, " %s\n", optstr)); ++options; } }
static void help(const apr_getopt_option_t *options, apr_pool_t *pool) { svn_error_clear (svn_cmdline_fprintf (stdout, pool, _("usage: svn-rep-sharing-stats [OPTIONS] REPOS_PATH\n\n" " Prints the reference count statistics for representations\n" " in an FSFS repository.\n" "\n" " At least one of the options --data/--prop/--both must be specified.\n" "\n" "Valid options:\n"))); while (options->description) { const char *optstr; svn_opt_format_option(&optstr, options, TRUE, pool); svn_error_clear(svn_cmdline_fprintf(stdout, pool, " %s\n", optstr)); ++options; } svn_error_clear(svn_cmdline_fprintf(stdout, pool, "\n")); exit(0); }
int main(int argc, const char **argv) { svn_error_t *err = SVN_NO_ERROR; const svn_opt_subcommand_desc2_t *subcommand = NULL; opt_baton_t *opt_baton; svn_revnum_t latest_revision = SVN_INVALID_REVNUM; apr_pool_t *pool = NULL; const char *config_dir = NULL; const char *username = NULL; const char *password = NULL; svn_boolean_t no_auth_cache = FALSE; svn_boolean_t trust_server_cert = FALSE; svn_boolean_t non_interactive = FALSE; apr_array_header_t *config_options = NULL; apr_getopt_t *os; const char *first_arg; apr_array_header_t *received_opts; apr_allocator_t *allocator; int i; if (svn_cmdline_init ("svnrdump", stderr) != EXIT_SUCCESS) return EXIT_FAILURE; /* Create our top-level pool. Use a separate 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); opt_baton = apr_pcalloc(pool, sizeof(*opt_baton)); opt_baton->start_revision.kind = svn_opt_revision_unspecified; opt_baton->end_revision.kind = svn_opt_revision_unspecified; opt_baton->url = NULL; SVNRDUMP_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); os->interleave = TRUE; /* Options and arguments can be interleaved */ /* Set up our cancellation support. */ apr_signal(SIGINT, signal_handler); #ifdef SIGBREAK /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ apr_signal(SIGBREAK, signal_handler); #endif #ifdef SIGHUP apr_signal(SIGHUP, signal_handler); #endif #ifdef SIGTERM apr_signal(SIGTERM, signal_handler); #endif #ifdef SIGPIPE /* Disable SIGPIPE generation for the platforms that have it. */ apr_signal(SIGPIPE, SIG_IGN); #endif #ifdef SIGXFSZ /* Disable SIGXFSZ generation for the platforms that have it, otherwise * working with large files when compiled against an APR that doesn't have * large file support will crash the program, which is uncool. */ apr_signal(SIGXFSZ, SIG_IGN); #endif received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); while (1) { int opt; const char *opt_arg; apr_status_t status = apr_getopt_long(os, svnrdump__options, &opt, &opt_arg); if (APR_STATUS_IS_EOF(status)) break; if (status != APR_SUCCESS) { SVNRDUMP_ERR(usage(argv[0], pool)); exit(EXIT_FAILURE); } /* Stash the option code in an array before parsing it. */ APR_ARRAY_PUSH(received_opts, int) = opt; switch(opt) { case 'r': { /* Make sure we've not seen -r already. */ if (opt_baton->start_revision.kind != svn_opt_revision_unspecified) { err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Multiple revision arguments " "encountered; try '-r N:M' instead " "of '-r N -r M'")); return svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); } /* Parse the -r argument. */ if (svn_opt_parse_revision(&(opt_baton->start_revision), &(opt_baton->end_revision), opt_arg, pool) != 0) { const char *utf8_opt_arg; 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 svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); } } break; case 'q': opt_baton->quiet = TRUE; break; case opt_config_dir: config_dir = opt_arg; break; case opt_version: opt_baton->version = TRUE; break; case 'h': opt_baton->help = TRUE; break; case opt_auth_username: SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&username, opt_arg, pool)); break; case opt_auth_password: SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool)); break; case opt_auth_nocache: no_auth_cache = TRUE; break; case opt_non_interactive: non_interactive = TRUE; break; case opt_incremental: opt_baton->incremental = TRUE; break; case opt_trust_server_cert: trust_server_cert = TRUE; break; case opt_config_option: if (!config_options) config_options = apr_array_make(pool, 1, sizeof(svn_cmdline__config_argument_t*)); SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool)); SVNRDUMP_ERR(svn_cmdline__parse_config_option(config_options, opt_arg, pool)); } } if (opt_baton->help) { subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table, "help"); } if (subcommand == NULL) { if (os->ind >= os->argc) { if (opt_baton->version) { /* Use the "help" subcommand to handle the "--version" option. */ static const svn_opt_subcommand_desc2_t pseudo_cmd = { "--version", help_cmd, {0}, "", { opt_version, /* must accept its own option */ 'q', /* --quiet */ } }; subcommand = &pseudo_cmd; } else { SVNRDUMP_ERR(help_cmd(NULL, NULL, pool)); svn_pool_destroy(pool); exit(EXIT_FAILURE); } } else { first_arg = os->argv[os->ind++]; subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table, first_arg); if (subcommand == NULL) { const char *first_arg_utf8; err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, pool); if (err) return svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); svn_error_clear(svn_cmdline_fprintf(stderr, pool, _("Unknown command: '%s'\n"), first_arg_utf8)); SVNRDUMP_ERR(help_cmd(NULL, NULL, pool)); svn_pool_destroy(pool); exit(EXIT_FAILURE); } } } /* Check that the subcommand wasn't passed any inappropriate options. */ for (i = 0; i < received_opts->nelts; i++) { int opt_id = APR_ARRAY_IDX(received_opts, i, int); /* All commands implicitly accept --help, so just skip over this when we see it. Note that we don't want to include this option in their "accepted options" list because it would be awfully redundant to display it in every commands' help text. */ if (opt_id == 'h' || opt_id == '?') continue; if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL)) { const char *optstr; const apr_getopt_option_t *badopt = svn_opt_get_option_from_code2(opt_id, svnrdump__options, subcommand, pool); svn_opt_format_option(&optstr, badopt, FALSE, pool); if (subcommand->name[0] == '-') SVN_INT_ERR(help_cmd(NULL, NULL, pool)); else svn_error_clear(svn_cmdline_fprintf( stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n" "Type 'svnrdump help %s' for usage.\n"), subcommand->name, optstr, subcommand->name)); svn_pool_destroy(pool); return EXIT_FAILURE; } } if (subcommand && strcmp(subcommand->name, "--version") == 0) { SVNRDUMP_ERR(version(argv[0], opt_baton->quiet, pool)); svn_pool_destroy(pool); exit(EXIT_SUCCESS); } if (subcommand && strcmp(subcommand->name, "help") == 0) { SVNRDUMP_ERR(help_cmd(os, opt_baton, pool)); svn_pool_destroy(pool); exit(EXIT_SUCCESS); } /* --trust-server-cert can only be used with --non-interactive */ if (trust_server_cert && !non_interactive) { err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("--trust-server-cert requires " "--non-interactive")); return svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); } /* Expect one more non-option argument: the repository URL. */ if (os->ind != os->argc - 1) { SVNRDUMP_ERR(usage(argv[0], pool)); svn_pool_destroy(pool); exit(EXIT_FAILURE); } else { const char *repos_url; SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&repos_url, os->argv[os->ind], pool)); if (! svn_path_is_url(repos_url)) { err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, 0, "Target '%s' is not a URL", repos_url); SVNRDUMP_ERR(err); svn_pool_destroy(pool); exit(EXIT_FAILURE); } opt_baton->url = svn_uri_canonicalize(repos_url, pool); } SVNRDUMP_ERR(init_client_context(&(opt_baton->ctx), non_interactive, username, password, config_dir, no_auth_cache, trust_server_cert, config_options, pool)); SVNRDUMP_ERR(svn_client_open_ra_session(&(opt_baton->session), opt_baton->url, opt_baton->ctx, pool)); /* Have sane opt_baton->start_revision and end_revision defaults if unspecified. */ SVNRDUMP_ERR(svn_ra_get_latest_revnum(opt_baton->session, &latest_revision, pool)); /* Make sure any provided revisions make sense. */ SVNRDUMP_ERR(validate_and_resolve_revisions(opt_baton, latest_revision, pool)); /* Dispatch the subcommand */ SVNRDUMP_ERR((*subcommand->cmd_func)(os, opt_baton, pool)); svn_pool_destroy(pool); return EXIT_SUCCESS; }
/* Same as print_command_info2(), but with deprecated struct revision. */ static svn_error_t * print_command_info(const svn_opt_subcommand_desc_t *cmd, const apr_getopt_option_t *options_table, svn_boolean_t help, apr_pool_t *pool, FILE *stream) { svn_boolean_t first_time; apr_size_t i; /* Print the canonical command name. */ SVN_ERR(svn_cmdline_fputs(cmd->name, stream, pool)); /* Print the list of aliases. */ first_time = TRUE; for (i = 0; i < SVN_OPT_MAX_ALIASES; i++) { if (cmd->aliases[i] == NULL) break; if (first_time) { SVN_ERR(svn_cmdline_fputs(" (", stream, pool)); first_time = FALSE; } else SVN_ERR(svn_cmdline_fputs(", ", stream, pool)); SVN_ERR(svn_cmdline_fputs(cmd->aliases[i], stream, pool)); } if (! first_time) SVN_ERR(svn_cmdline_fputs(")", stream, pool)); if (help) { const apr_getopt_option_t *option; svn_boolean_t have_options = FALSE; SVN_ERR(svn_cmdline_fprintf(stream, pool, ": %s", _(cmd->help))); /* Loop over all valid option codes attached to the subcommand */ for (i = 0; i < SVN_OPT_MAX_OPTIONS; i++) { if (cmd->valid_options[i]) { if (!have_options) { SVN_ERR(svn_cmdline_fputs(_("\nValid options:\n"), stream, pool)); have_options = TRUE; } /* convert each option code into an option */ option = svn_opt_get_option_from_code2(cmd->valid_options[i], options_table, NULL, pool); /* print the option's docstring */ if (option && option->description) { const char *optstr; svn_opt_format_option(&optstr, option, TRUE, pool); SVN_ERR(svn_cmdline_fprintf(stream, pool, " %s\n", optstr)); } } } if (have_options) SVN_ERR(svn_cmdline_fprintf(stream, pool, "\n")); } return SVN_NO_ERROR; }
int main (int argc, const char * const *argv) { svn_error_t *err; apr_status_t apr_err; apr_allocator_t *allocator; apr_pool_t *pool; const svn_opt_subcommand_desc_t *subcommand = NULL; struct svnindex_opt_state opt_state; apr_getopt_t *os; int opt_id; apr_array_header_t *received_opts; int i; /* Initialize the app. */ if (svn_cmdline_init ("svnindex", 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); received_opts = apr_array_make (pool, SVN_OPT_MAX_OPTIONS, sizeof (int)); /* Check library versions */ err = check_lib_versions (); if (err) return svn_cmdline_handle_exit_error (err, pool, "svnindex: "); /* Initialize the FS library. */ err = svn_fs_initialize (pool); if (err) return svn_cmdline_handle_exit_error (err, pool, "svnindex: "); if (argc <= 1) { subcommand_help (NULL, NULL, pool); svn_pool_destroy (pool); return EXIT_FAILURE; } /* Initialize opt_state. */ memset (&opt_state, 0, sizeof (opt_state)); opt_state.start_revision.kind = svn_opt_revision_unspecified; opt_state.end_revision.kind = svn_opt_revision_unspecified; /* 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, options_table, &opt_id, &opt_arg); if (APR_STATUS_IS_EOF (apr_err)) break; else if (apr_err) { subcommand_help (NULL, NULL, pool); svn_pool_destroy (pool); return EXIT_FAILURE; } /* Stash the option code in an array before parsing it. */ APR_ARRAY_PUSH (received_opts, int) = opt_id; switch (opt_id) { 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 svn_cmdline_handle_exit_error (err, pool, "svnindex: "); } 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 svn_cmdline_handle_exit_error (err, pool, "svnindex: "); } } break; case 'q': opt_state.quiet = TRUE; break; case 'h': case '?': opt_state.help = TRUE; break; case svnindex__version: opt_state.version = TRUE; opt_state.help = TRUE; break; case svnindex__db: err = svn_utf_cstring_to_utf8 (&opt_state.db, opt_arg, pool); if (err) return svn_cmdline_handle_exit_error (err, pool, "svnindex: "); break; case 'v': opt_state.verbose = TRUE; break; default: { subcommand_help (NULL, NULL, pool); svn_pool_destroy (pool); return EXIT_FAILURE; } } /* close `switch' */ } /* close `while' */ /* 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 just typos/mistakes. Whatever the case, the subcommand to actually run is subcommand_help(). */ if (opt_state.help) subcommand = svn_opt_get_canonical_subcommand (cmd_table, "help"); /* If we're not running the `help' subcommand, then look for a subcommand in the first argument. */ if (subcommand == NULL) { if (os->ind >= os->argc) { svn_error_clear (svn_cmdline_fprintf (stderr, pool, _("subcommand argument required\n"))); subcommand_help (NULL, NULL, pool); svn_pool_destroy (pool); return EXIT_FAILURE; } else { const char *first_arg = os->argv[os->ind++]; subcommand = svn_opt_get_canonical_subcommand (cmd_table, first_arg); if (subcommand == NULL) { const char* first_arg_utf8; err = svn_utf_cstring_to_utf8 (&first_arg_utf8, first_arg, pool); if (err) return svn_cmdline_handle_exit_error (err, pool, "svnindex: "); svn_error_clear (svn_cmdline_fprintf (stderr, pool, _("Unknown command: '%s'\n"), first_arg_utf8)); subcommand_help (NULL, NULL, pool); svn_pool_destroy (pool); return EXIT_FAILURE; } } } /* If there's a second argument, it's probably the repository. Every subcommand except `help' requires one, so we parse it out here and store it in opt_state. */ if (subcommand->cmd_func != subcommand_help) { err = parse_local_repos_path (os, &(opt_state.repository_path), pool); if(err) { svn_handle_error2 (err, stderr, FALSE, "svnindex: "); svn_opt_subcommand_help (subcommand->name, cmd_table, options_table, pool); svn_error_clear (err); svn_pool_destroy (pool); return EXIT_FAILURE; } } /* Check that the subcommand wasn't passed any inappropriate options. */ for (i = 0; i < received_opts->nelts; i++) { opt_id = APR_ARRAY_IDX (received_opts, i, int); /* All commands implicitly accept --help, so just skip over this when we see it. Note that we don't want to include this option in their "accepted options" list because it would be awfully redundant to display it in every commands' help text. */ if (opt_id == 'h' || opt_id == '?') continue; if (! svn_opt_subcommand_takes_option (subcommand, opt_id)) { const char *optstr; const apr_getopt_option_t *badopt = svn_opt_get_option_from_code (opt_id, options_table); svn_opt_format_option (&optstr, badopt, FALSE, pool); svn_error_clear (svn_cmdline_fprintf (stderr, pool, _("subcommand '%s' doesn't accept option '%s'\n" "Type 'svnindex help %s' for usage.\n"), subcommand->name, optstr, subcommand->name)); svn_pool_destroy (pool); return EXIT_FAILURE; } } /* Set up our cancellation support. */ setup_cancellation_signals (signal_handler); #ifdef SIGPIPE /* Disable SIGPIPE generation for the platforms that have it. */ apr_signal(SIGPIPE, SIG_IGN); #endif /* Run the subcommand. */ err = (*subcommand->cmd_func) (os, &opt_state, pool); if (err) { if (err->apr_err == SVN_ERR_CL_ARG_PARSING_ERROR) { svn_handle_error2 (err, stderr, FALSE, "svnindex: "); svn_opt_subcommand_help (subcommand->name, cmd_table, options_table, pool); } else svn_handle_error2 (err, stderr, FALSE, "svnindex: "); svn_error_clear (err); svn_pool_destroy (pool); return EXIT_FAILURE; } else { svn_pool_destroy (pool); /* Ensure that everything is written to stdout, so the user will see any print errors. */ err = svn_cmdline_fflush (stdout); if (err) { svn_handle_error2 (err, stderr, FALSE, "svnindex: "); svn_error_clear (err); return EXIT_FAILURE; } return EXIT_SUCCESS; } }
/* * 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; const svn_opt_subcommand_desc2_t *subcommand = NULL; struct svnauthz_opt_state opt_state = { 0 }; apr_getopt_t *os; apr_array_header_t *received_opts; int i; /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); /* Initialize opt_state */ opt_state.username = opt_state.fspath = opt_state.repos_name = NULL; opt_state.txn = opt_state.repos_path = opt_state.groups_file = NULL; /* Parse options. */ SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); os->interleave = 1; if (!use_compat_mode(argv[0], pool)) { while (1) { int opt; const char *arg; apr_status_t status = apr_getopt_long(os, options_table, &opt, &arg); if (APR_STATUS_IS_EOF(status)) break; if (status != APR_SUCCESS) { SVN_ERR(subcommand_help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; } /* Stash the option code in an array before parsing it. */ APR_ARRAY_PUSH(received_opts, int) = opt; switch (opt) { case 'h': case '?': opt_state.help = TRUE; break; case 't': SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.txn, arg, pool)); break; case 'R': opt_state.recursive = TRUE; break; case svnauthz__version: opt_state.version = TRUE; break; case svnauthz__username: SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.username, arg, pool)); break; case svnauthz__path: SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.fspath, arg, pool)); opt_state.fspath = svn_fspath__canonicalize(opt_state.fspath, pool); break; case svnauthz__repos: SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.repos_name, arg, pool)); break; case svnauthz__is: SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.is, arg, pool)); break; case svnauthz__groups_file: SVN_ERR( svn_utf_cstring_to_utf8(&opt_state.groups_file, arg, pool)); break; default: { SVN_ERR(subcommand_help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; } } } } else { /* Pre 1.8 compatibility mode. */ if (argc == 1) /* No path argument */ subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help"); else subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "validate"); } /* 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 just typos/mistakes. Whatever the case, the subcommand to actually run is subcommand_help(). */ if (opt_state.help) subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help"); if (subcommand == NULL) { if (os->ind >= os->argc) { if (opt_state.version) { /* Use the "help" subcommand to handle the "--version" option. */ static const svn_opt_subcommand_desc2_t pseudo_cmd = { "--version", subcommand_help, {0}, "", {svnauthz__version /* must accept its own option */ } }; subcommand = &pseudo_cmd; } else { svn_error_clear(svn_cmdline_fprintf(stderr, pool, ("subcommand argument required\n"))); SVN_ERR(subcommand_help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; } } else { const char *first_arg = os->argv[os->ind++]; subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg); if (subcommand == NULL) { const char *first_arg_utf8; os->ind++; 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"), first_arg_utf8)); SVN_ERR(subcommand_help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; } } } /* Every subcommand except `help' requires one or two non-option arguments. Parse them and store them in opt_state.*/ if (subcommand->cmd_func != subcommand_help) { /* Consume a non-option argument (repos_path) if --transaction */ if (opt_state.txn) { if (os->ind +2 != argc) { return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, ("Repository and authz file arguments " "required")); } SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.repos_path, os->argv[os->ind], pool)); os->ind++; opt_state.repos_path = svn_dirent_internal_style(opt_state.repos_path, pool); } /* Exactly 1 non-option argument */ if (os->ind + 1 != argc) { return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, ("Authz file argument required")); } /* Grab AUTHZ_FILE from argv. */ SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.authz_file, os->argv[os->ind], pool)); /* Canonicalize opt_state.authz_file appropriately. */ SVN_ERR(canonicalize_access_file(&opt_state.authz_file, opt_state.authz_file, opt_state.txn != NULL, pool)); /* Same for opt_state.groups_file if it is present. */ if (opt_state.groups_file) { SVN_ERR(canonicalize_access_file(&opt_state.groups_file, opt_state.groups_file, opt_state.txn != NULL, pool)); } } /* Check that the subcommand wasn't passed any inappropriate options. */ for (i = 0; i < received_opts->nelts; i++) { int opt_id = APR_ARRAY_IDX(received_opts, i, int); /* All commands implicitly accept --help, so just skip over this when we see it. Note that we don't want to include this option in their "accepted options" list because it would be awfully redundant to display it in every commands' help text. */ if (opt_id == 'h' || opt_id == '?') continue; if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL)) { const char *optstr; const apr_getopt_option_t *badopt = svn_opt_get_option_from_code2(opt_id, options_table, subcommand, pool); svn_opt_format_option(&optstr, badopt, FALSE, pool); if (subcommand->name[0] == '-') SVN_ERR(subcommand_help(NULL, NULL, pool)); else svn_error_clear(svn_cmdline_fprintf(stderr, pool, ("Subcommand '%s' doesn't accept option '%s'\n" "Type 'svnauthz help %s' for usage.\n"), subcommand->name, optstr, subcommand->name)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; } } /* Run the subcommand. */ err = (*subcommand->cmd_func)(os, &opt_state, pool); if (err) { if (err->apr_err == SVN_ERR_CL_INSUFFICIENT_ARGS || err->apr_err == SVN_ERR_CL_ARG_PARSING_ERROR) { /* For argument-related problems, suggest using the 'help' subcommand. */ err = svn_error_quick_wrap(err, ("Try 'svnauthz help' for more info")); } else if (err->apr_err == SVN_ERR_AUTHZ_INVALID_CONFIG || err->apr_err == SVN_ERR_MALFORMED_FILE) { /* Follow our contract that says we exit with 1 if the file does not validate. */ *exit_code = 1; return err; } else if (err->apr_err == SVN_ERR_AUTHZ_UNREADABLE || err->apr_err == SVN_ERR_AUTHZ_UNWRITABLE || err->apr_err == SVN_ERR_AUTHZ_PARTIALLY_READABLE) { /* Follow our contract that says we exit with 3 if --is does not * match. */ *exit_code = 3; return err; } return err; } return SVN_NO_ERROR; }