diff options
Diffstat (limited to 'subversion/svnlook/svnlook.c')
-rw-r--r-- | subversion/svnlook/svnlook.c | 237 |
1 files changed, 133 insertions, 104 deletions
diff --git a/subversion/svnlook/svnlook.c b/subversion/svnlook/svnlook.c index 8162e414e46dd..e06933f38ca93 100644 --- a/subversion/svnlook/svnlook.c +++ b/subversion/svnlook/svnlook.c @@ -54,11 +54,11 @@ #include "svn_version.h" #include "svn_xml.h" -#include "private/svn_diff_private.h" #include "private/svn_cmdline_private.h" +#include "private/svn_diff_private.h" #include "private/svn_fspath.h" #include "private/svn_io_private.h" -#include "private/svn_subr_private.h" +#include "private/svn_sorts_private.h" #include "svn_private_config.h" @@ -102,7 +102,8 @@ enum svnlook__ignore_properties, svnlook__properties_only, svnlook__diff_cmd, - svnlook__show_inherited_props + svnlook__show_inherited_props, + svnlook__no_newline }; /* @@ -143,6 +144,9 @@ static const apr_getopt_option_t options_table[] = {"properties-only", svnlook__properties_only, 0, N_("show only properties during the operation")}, + {"no-newline", svnlook__no_newline, 0, + N_("do not output the trailing newline")}, + {"non-recursive", 'N', 0, N_("operate on single directory only")}, @@ -187,6 +191,8 @@ static const apr_getopt_option_t options_table[] = " " " --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")}, {"quiet", 'q', 0, @@ -300,7 +306,7 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = {"youngest", subcommand_youngest, {0}, N_("usage: svnlook youngest REPOS_PATH\n\n" "Print the youngest revision number.\n"), - {0} }, + {svnlook__no_newline} }, { NULL, NULL, {0}, NULL, {0} } }; @@ -333,6 +339,7 @@ struct svnlook_opt_state svn_boolean_t properties_only; /* --properties-only */ const char *diff_cmd; /* --diff-cmd */ svn_boolean_t show_inherited_props; /* --show-inherited-props */ + svn_boolean_t no_newline; /* --no-newline */ }; @@ -804,7 +811,9 @@ display_prop_diffs(svn_stream_t *outstream, SVN_ERR(svn_diff__display_prop_diffs( outstream, encoding, propchanges, original_props, - FALSE /* pretty_print_mergeinfo */, pool)); + FALSE /* pretty_print_mergeinfo */, + -1 /* context_size */, + check_cancel, NULL, pool)); return SVN_NO_ERROR; } @@ -1058,11 +1067,12 @@ print_diff_tree(svn_stream_t *out_stream, SVN_ERR(generate_label(&orig_label, base_root, base_path, pool)); SVN_ERR(generate_label(&new_label, root, path, pool)); - SVN_ERR(svn_diff_file_output_unified3 - (out_stream, diff, orig_path, new_path, + SVN_ERR(svn_diff_file_output_unified4( + out_stream, diff, orig_path, new_path, orig_label, new_label, svn_cmdline_output_encoding(pool), NULL, - opts->show_c_function, pool)); + opts->show_c_function, opts->context_size, + check_cancel, NULL, pool)); SVN_ERR(svn_stream_printf_from_utf8(out_stream, encoding, pool, "\n")); diff_header_printed = TRUE; @@ -1599,7 +1609,7 @@ print_history(void *baton, { phb->count++; if (phb->count >= phb->limit) - /* Not L10N'd, since this error is supressed by the caller. */ + /* Not L10N'd, since this error is suppressed by the caller. */ return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, _("History item limit reached")); } @@ -1696,9 +1706,14 @@ do_pget(svnlook_ctxt_t *c, if (path == NULL) { /* We're operating on a revprop (e.g. c->is_revision). */ - err_msg = apr_psprintf(pool, - _("Property '%s' not found on revision %ld"), - propname, c->rev_id); + if (SVN_IS_VALID_REVNUM(c->rev_id)) + err_msg = apr_psprintf(pool, + _("Property '%s' not found on revision %ld"), + propname, c->rev_id); + else + err_msg = apr_psprintf(pool, + _("Property '%s' not found on transaction %s"), + propname, c->txn_name); } else { @@ -1761,8 +1776,7 @@ do_pget(svnlook_ctxt_t *c, else { svn_string_t *propval = - svn__apr_hash_index_val(apr_hash_first(pool, - elt->prop_hash)); + apr_hash_this_val(apr_hash_first(pool, elt->prop_hash)); SVN_ERR(svn_stream_printf( stdout_stream, pool, "%s - ", @@ -1877,7 +1891,8 @@ do_plist(svnlook_ctxt_t *c, svn_xml_make_header2(&sb, "UTF-8", pool); /* "<properties>" */ - svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "properties", NULL); + svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "properties", + SVN_VA_NULL); } if (inherited_props) @@ -1896,7 +1911,7 @@ do_plist(svnlook_ctxt_t *c, svn_xml_make_open_tag( &sb, pool, svn_xml_normal, "target", "path", svn_fspath__canonicalize(elt->path_or_url, pool), - NULL); + SVN_VA_NULL); SVN_ERR(svn_cmdline__print_xml_prop_hash(&sb, elt->prop_hash, !verbose, TRUE, pool)); @@ -1923,19 +1938,19 @@ do_plist(svnlook_ctxt_t *c, char *revstr = apr_psprintf(pool, "%ld", c->rev_id); svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops", - "rev", revstr, NULL); + "rev", revstr, SVN_VA_NULL); } else { svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops", - "txn", c->txn_name, NULL); + "txn", c->txn_name, SVN_VA_NULL); } } else { /* "<target ...>" */ svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target", - "path", path, NULL); + "path", path, SVN_VA_NULL); } } @@ -1944,8 +1959,8 @@ do_plist(svnlook_ctxt_t *c, for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi)) { - const char *pname = svn__apr_hash_index_key(hi); - svn_string_t *propval = svn__apr_hash_index_val(hi); + const char *pname = apr_hash_this_key(hi); + svn_string_t *propval = apr_hash_this_val(hi); SVN_ERR(check_cancel(NULL)); @@ -1982,7 +1997,7 @@ do_plist(svnlook_ctxt_t *c, } else if (xml) svn_xml_make_open_tag(&sb, pool, svn_xml_self_closing, "property", - "name", pname, NULL); + "name", pname, SVN_VA_NULL); else printf(" %s\n", pname); } @@ -2003,10 +2018,11 @@ do_plist(svnlook_ctxt_t *c, /* "</properties>" */ svn_xml_make_close_tag(&sb, pool, "properties"); + errno = 0; if (fputs(sb->data, stdout) == EOF) { - if (errno) - return svn_error_wrap_apr(errno, _("Write error")); + if (apr_get_os_error()) /* is errno on POSIX */ + return svn_error_wrap_apr(apr_get_os_error(), _("Write error")); else return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL, NULL); } @@ -2074,8 +2090,8 @@ get_ctxt_baton(svnlook_ctxt_t **baton_p, { svnlook_ctxt_t *baton = apr_pcalloc(pool, sizeof(*baton)); - SVN_ERR(svn_repos_open2(&(baton->repos), opt_state->repos_path, NULL, - pool)); + SVN_ERR(svn_repos_open3(&(baton->repos), opt_state->repos_path, NULL, + pool, pool)); baton->fs = svn_repos_fs(baton->repos); svn_fs_set_warning_func(baton->fs, warning_func, NULL); baton->show_ids = opt_state->show_ids; @@ -2214,11 +2230,12 @@ subcommand_help(apr_getopt_t *os, void *baton, apr_pool_t *pool) struct svnlook_opt_state *opt_state = baton; const char *header = _("general usage: svnlook SUBCOMMAND REPOS_PATH [ARGS & OPTIONS ...]\n" + "Subversion repository inspection tool.\n" + "Type 'svnlook help <subcommand>' for help on a specific subcommand.\n" + "Type 'svnlook --version' to see the program version and FS modules.\n" "Note: any subcommand which takes the '--revision' and '--transaction'\n" " options will, if invoked without one of those options, act on\n" " the repository's youngest revision.\n" - "Type 'svnlook help <subcommand>' for help on a specific subcommand.\n" - "Type 'svnlook --version' to see the program version and FS modules.\n" "\n" "Available subcommands:\n"); @@ -2409,7 +2426,8 @@ subcommand_youngest(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(check_number_of_args(opt_state, 0)); SVN_ERR(get_ctxt_baton(&c, opt_state, pool)); - SVN_ERR(svn_cmdline_printf(pool, "%ld\n", c->rev_id)); + SVN_ERR(svn_cmdline_printf(pool, "%ld%s", c->rev_id, + opt_state->no_newline ? "" : "\n")); return SVN_NO_ERROR; } @@ -2433,12 +2451,16 @@ subcommand_uuid(apr_getopt_t *os, void *baton, apr_pool_t *pool) /*** Main. ***/ -int -main(int argc, const char *argv[]) +/* + * 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; apr_status_t apr_err; - apr_pool_t *pool; const svn_opt_subcommand_desc2_t *subcommand = NULL; struct svnlook_opt_state opt_state; @@ -2447,32 +2469,19 @@ main(int argc, const char *argv[]) apr_array_header_t *received_opts; int i; - /* Initialize the app. */ - if (svn_cmdline_init("svnlook", stderr) != EXIT_SUCCESS) - return EXIT_FAILURE; - - /* Create our top-level pool. Use a separate mutexless allocator, - * given this application is single threaded. - */ - pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE)); - 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, "svnlook: "); + SVN_ERR(check_lib_versions()); /* Initialize the FS library. */ - err = svn_fs_initialize(pool); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "svnlook: "); + SVN_ERR(svn_fs_initialize(pool)); if (argc <= 1) { - SVN_INT_ERR(subcommand_help(NULL, NULL, pool)); - svn_pool_destroy(pool); - return EXIT_FAILURE; + SVN_ERR(subcommand_help(NULL, NULL, pool)); + *exit_code = EXIT_FAILURE; + return SVN_NO_ERROR; } /* Initialize opt_state. */ @@ -2480,9 +2489,7 @@ main(int argc, const char *argv[]) opt_state.rev = SVN_INVALID_REVNUM; /* Parse options. */ - err = svn_cmdline__getopt_init(&os, argc, argv, pool); - if (err) - return svn_cmdline_handle_exit_error(err, pool, "svnlook: "); + SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); os->interleave = 1; while (1) @@ -2495,9 +2502,9 @@ main(int argc, const char *argv[]) break; else if (apr_err) { - SVN_INT_ERR(subcommand_help(NULL, NULL, pool)); - svn_pool_destroy(pool); - return EXIT_FAILURE; + 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. */ @@ -2512,9 +2519,8 @@ main(int argc, const char *argv[]) if ((! SVN_IS_VALID_REVNUM(opt_state.rev)) || (! digits_end) || *digits_end) - SVN_INT_ERR(svn_error_create - (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, - _("Invalid revision number supplied"))); + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Invalid revision number supplied")); } break; @@ -2561,15 +2567,13 @@ main(int argc, const char *argv[]) opt_state.limit = strtol(opt_arg, &end, 10); if (end == opt_arg || *end != '\0') { - err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, - _("Non-numeric limit argument given")); - return svn_cmdline_handle_exit_error(err, pool, "svnlook: "); + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Non-numeric limit argument given")); } if (opt_state.limit <= 0) { - err = svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, + return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, _("Argument to --limit must be positive")); - return svn_cmdline_handle_exit_error(err, pool, "svnlook: "); } } break; @@ -2614,27 +2618,31 @@ main(int argc, const char *argv[]) opt_state.show_inherited_props = TRUE; break; + case svnlook__no_newline: + opt_state.no_newline = TRUE; + break; + default: - SVN_INT_ERR(subcommand_help(NULL, NULL, pool)); - svn_pool_destroy(pool); - return EXIT_FAILURE; + SVN_ERR(subcommand_help(NULL, NULL, pool)); + *exit_code = EXIT_FAILURE; + return SVN_NO_ERROR; } } /* The --transaction and --revision options may not co-exist. */ if ((opt_state.rev != SVN_INVALID_REVNUM) && opt_state.txn) - SVN_INT_ERR(svn_error_create + return svn_error_create (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL, _("The '--transaction' (-t) and '--revision' (-r) arguments " - "cannot co-exist"))); + "cannot co-exist")); /* The --show-inherited-props and --revprop options may not co-exist. */ if (opt_state.show_inherited_props && opt_state.revprop) - SVN_INT_ERR(svn_error_create + return svn_error_create (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL, _("Cannot use the '--show-inherited-props' option with the " - "'--revprop' option"))); + "'--revprop' option")); /* 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 @@ -2665,9 +2673,9 @@ main(int argc, const char *argv[]) svn_error_clear (svn_cmdline_fprintf(stderr, pool, _("Subcommand argument required\n"))); - SVN_INT_ERR(subcommand_help(NULL, NULL, pool)); - svn_pool_destroy(pool); - return EXIT_FAILURE; + SVN_ERR(subcommand_help(NULL, NULL, pool)); + *exit_code = EXIT_FAILURE; + return SVN_NO_ERROR; } } else @@ -2677,15 +2685,13 @@ main(int argc, const char *argv[]) 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, "svnlook: "); + 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_INT_ERR(subcommand_help(NULL, NULL, pool)); + SVN_ERR(subcommand_help(NULL, NULL, pool)); /* Be kind to people who try 'svnlook verify'. */ if (strcmp(first_arg_utf8, "verify") == 0) @@ -2695,9 +2701,8 @@ main(int argc, const char *argv[]) _("Try 'svnadmin verify' instead.\n"))); } - - svn_pool_destroy(pool); - return EXIT_FAILURE; + *exit_code = EXIT_FAILURE; + return SVN_NO_ERROR; } } } @@ -2716,9 +2721,9 @@ main(int argc, const char *argv[]) /* Get the repository. */ if (os->ind < os->argc) { - SVN_INT_ERR(svn_utf_cstring_to_utf8(&repos_path, - os->argv[os->ind++], - pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&repos_path, + os->argv[os->ind++], + pool)); repos_path = svn_dirent_internal_style(repos_path, pool); } @@ -2727,9 +2732,9 @@ main(int argc, const char *argv[]) svn_error_clear (svn_cmdline_fprintf(stderr, pool, _("Repository argument required\n"))); - SVN_INT_ERR(subcommand_help(NULL, NULL, pool)); - svn_pool_destroy(pool); - return EXIT_FAILURE; + SVN_ERR(subcommand_help(NULL, NULL, pool)); + *exit_code = EXIT_FAILURE; + return SVN_NO_ERROR; } else if (svn_path_is_url(repos_path)) { @@ -2737,8 +2742,8 @@ main(int argc, const char *argv[]) (svn_cmdline_fprintf(stderr, pool, _("'%s' is a URL when it should be a path\n"), repos_path)); - svn_pool_destroy(pool); - return EXIT_FAILURE; + *exit_code = EXIT_FAILURE; + return SVN_NO_ERROR; } opt_state.repos_path = repos_path; @@ -2746,8 +2751,7 @@ main(int argc, const char *argv[]) /* Get next arg (arg1), if any. */ if (os->ind < os->argc) { - SVN_INT_ERR(svn_utf_cstring_to_utf8 - (&arg1, os->argv[os->ind++], pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&arg1, os->argv[os->ind++], pool)); arg1 = svn_dirent_internal_style(arg1, pool); } opt_state.arg1 = arg1; @@ -2755,8 +2759,7 @@ main(int argc, const char *argv[]) /* Get next arg (arg2), if any. */ if (os->ind < os->argc) { - SVN_INT_ERR(svn_utf_cstring_to_utf8 - (&arg2, os->argv[os->ind++], pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&arg2, os->argv[os->ind++], pool)); arg2 = svn_dirent_internal_style(arg2, pool); } opt_state.arg2 = arg2; @@ -2782,7 +2785,7 @@ main(int argc, const char *argv[]) pool); svn_opt_format_option(&optstr, badopt, FALSE, pool); if (subcommand->name[0] == '-') - SVN_INT_ERR(subcommand_help(NULL, NULL, pool)); + SVN_ERR(subcommand_help(NULL, NULL, pool)); else svn_error_clear (svn_cmdline_fprintf @@ -2790,8 +2793,8 @@ main(int argc, const char *argv[]) _("Subcommand '%s' doesn't accept option '%s'\n" "Type 'svnlook help %s' for usage.\n"), subcommand->name, optstr, subcommand->name)); - svn_pool_destroy(pool); - return EXIT_FAILURE; + *exit_code = EXIT_FAILURE; + return SVN_NO_ERROR; } } @@ -2832,14 +2835,40 @@ main(int argc, const char *argv[]) err = svn_error_quick_wrap(err, _("Try 'svnlook help' for more info")); } - return svn_cmdline_handle_exit_error(err, pool, "svnlook: "); + return err; } - else + + return SVN_NO_ERROR; +} + +int +main(int argc, const char *argv[]) +{ + apr_pool_t *pool; + int exit_code = EXIT_SUCCESS; + svn_error_t *err; + + /* Initialize the app. */ + if (svn_cmdline_init("svnlook", stderr) != EXIT_SUCCESS) + return EXIT_FAILURE; + + /* Create our top-level pool. Use a separate mutexless allocator, + * given this application is single threaded. + */ + pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE)); + + 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) { - svn_pool_destroy(pool); - /* Ensure everything is printed on stdout, so the user sees any - print errors. */ - SVN_INT_ERR(svn_cmdline_fflush(stdout)); - return EXIT_SUCCESS; + exit_code = EXIT_FAILURE; + svn_cmdline_handle_exit_error(err, NULL, "svnlook: "); } + + svn_pool_destroy(pool); + return exit_code; } |