Modified: subversion/branches/better-pristines/subversion/svn/notify.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svn/notify.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svn/notify.c (original) +++ subversion/branches/better-pristines/subversion/svn/notify.c Tue Jan 2 19:52:28 2018 @@ -210,7 +210,7 @@ svn_cl__conflict_stats_get_paths(apr_arr } } - svn_hash_keys(conflicted_paths, all_conflicts, result_pool); + SVN_ERR(svn_hash_keys(conflicted_paths, all_conflicts, result_pool)); svn_sort__array(*conflicted_paths, svn_sort_compare_paths); return SVN_NO_ERROR;
Modified: subversion/branches/better-pristines/subversion/svn/svn.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svn/svn.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svn/svn.c (original) +++ subversion/branches/better-pristines/subversion/svn/svn.c Tue Jan 2 19:52:28 2018 @@ -68,6 +68,7 @@ use the short option letter as identifier. */ typedef enum svn_cl__longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_autoprops, opt_changelist, @@ -145,7 +146,10 @@ typedef enum svn_cl__longopt_t { opt_show_item, opt_adds_as_modification, opt_vacuum_pristines, - opt_compatible_version, + opt_delete, + opt_keep_shelved, + opt_list, + opt_compatible_version } svn_cl__longopt_t; @@ -201,6 +205,9 @@ const apr_getopt_option_t svn_cl__option N_("specify a password ARG (caution: on many operating\n" " " "systems, other users will be able to see this)")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"extensions", 'x', 1, N_("Specify differencing options for external diff or\n" " " @@ -405,7 +412,9 @@ const apr_getopt_option_t svn_cl__option {"search", opt_search, 1, N_("use ARG as search pattern (glob syntax, case-\n" " " - "and accent-insensitive)")}, + "and accent-insensitive, may require quotation marks\n" + " " + "to prevent shell expansion)")}, {"search-and", opt_search_and, 1, N_("combine ARG with the previous search pattern")}, {"log", opt_mergeinfo_log, 0, @@ -455,7 +464,7 @@ const apr_getopt_option_t svn_cl__option " 'wc-root' root of TARGET's working copy")}, {"adds-as-modification", opt_adds_as_modification, 0, - N_("Local additions are merged with incoming additions " + N_("Local additions are merged with incoming additions\n" " " "instead of causing a tree conflict. Use of this\n" " " @@ -466,6 +475,10 @@ const apr_getopt_option_t svn_cl__option {"vacuum-pristines", opt_vacuum_pristines, 0, N_("remove unreferenced pristines from .svn directory")}, + {"list", opt_list, 0, N_("list shelved patches")}, + {"keep-shelved", opt_keep_shelved, 0, N_("do not delete the shelved patch")}, + {"delete", opt_delete, 0, N_("delete the shelved patch")}, + {"compatible-version", opt_compatible_version, 1, N_("use working copy format compatible with Subversion\n" " " @@ -501,7 +514,8 @@ const apr_getopt_option_t svn_cl__option command to take these arguments allows scripts to just pass them 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_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_no_auth_cache, opt_non_interactive, opt_force_interactive, opt_trust_server_cert, opt_trust_server_cert_failures, opt_config_dir, opt_config_options, 0 @@ -799,7 +813,34 @@ const svn_opt_subcommand_desc2_t svn_cl_ opt_changelist, opt_include_externals, opt_show_item, opt_no_newline} }, - { "list", svn_cl__list, {"ls"}, N_ + { "list", svn_cl__list, {"ls"}, +#if defined(WIN32) + N_ + ("List directory entries in the repository.\n" + "usage: list [TARGET[@REV]...]\n" + "\n" + " List each TARGET file and the contents of each TARGET directory as\n" + " they exist in the repository. If TARGET is a working copy path, the\n" + " corresponding repository URL will be used. If specified, REV determines\n" + " in which revision the target is first looked up.\n" + "\n" + " The default TARGET is '.', meaning the repository URL of the current\n" + " working directory.\n" + "\n" + " Multiple --search patterns may be specified and the output will be\n" + " reduced to those paths whose last segment - i.e. the file or directory\n" + " name - contains a sub-string matching at least one of these patterns\n" + " (Windows only).\n" + "\n" + " With --verbose, the following fields will be shown for each item:\n" + "\n" + " Revision number of the last commit\n" + " Author of the last commit\n" + " If locked, the letter 'O'. (Use 'svn info URL' to see details)\n" + " Size (in bytes)\n" + " Date and time of the last commit\n"), +#else + N_ ("List directory entries in the repository.\n" "usage: list [TARGET[@REV]...]\n" "\n" @@ -822,6 +863,7 @@ const svn_opt_subcommand_desc2_t svn_cl_ " If locked, the letter 'O'. (Use 'svn info URL' to see details)\n" " Size (in bytes)\n" " Date and time of the last commit\n"), +#endif {'r', 'v', 'R', opt_depth, opt_incremental, opt_xml, opt_include_externals, opt_search}, }, @@ -1655,6 +1697,74 @@ const svn_opt_subcommand_desc2_t svn_cl_ " the output of 'svn help merge' for 'undo'.\n"), {opt_targets, 'R', opt_depth, 'q', opt_changelist} }, + { "shelve", svn_cl__shelve, {0}, N_ + ("Put a local change aside, as if putting it on a shelf.\n" + "usage: 1. shelve [--keep-local] NAME [PATH...]\n" + " 2. shelve --delete NAME\n" + " 3. shelve --list\n" + "\n" + " 1. Save the local change in the given PATHs to a patch file, and\n" + " revert that change from the WC unless '--keep-local' is given.\n" + " If a log message is given with '-m' or '-F', include it at the\n" + " beginning of the patch file.\n" + "\n" + " 2. Delete the shelved change NAME.\n" + " (A backup is kept, named with a '.bak' extension.)\n" + "\n" + " 3. List shelved changes. Include the first line of any log message\n" + " and some details about the contents of the change, unless '-q' is\n" + " given.\n" + "\n" + " The kinds of change you can shelve are those supported by 'svn diff'\n" + " and 'svn patch'. The following are currently NOT supported:\n" + " mergeinfo changes, copies, moves, mkdir, rmdir,\n" + " 'binary' content, uncommittable states\n" + "\n" + " To bring back a shelved change, use 'svn unshelve NAME'.\n" + "\n" + " A shelved change is stored as a patch file, .svn/shelves/NAME.patch\n" + "\n" + " The shelving feature is EXPERIMENTAL. This command is likely to change\n" + " in the next release, and there is no promise of backward compatibility.\n" + ), + {opt_delete, opt_list, 'q', opt_dry_run, opt_keep_local, + opt_depth, opt_targets, opt_changelist, + /* almost SVN_CL__LOG_MSG_OPTIONS but not currently opt_with_revprop: */ + 'm', 'F', opt_force_log, opt_editor_cmd, opt_encoding, + } }, + + { "unshelve", svn_cl__unshelve, {0}, N_ + ("Bring a shelved change back to a local change in the WC.\n" + "usage: 1. unshelve [--keep-shelved] [NAME]\n" + " 2. unshelve --list\n" + "\n" + " 1. Apply the shelved change NAME to the working copy.\n" + " Delete the patch unless the '--keep-shelved' option is given.\n" + " (A backup is kept, named with a '.bak' extension.)\n" + " NAME defaults to the most recent shelved change.\n" + "\n" + " 2. List shelved changes. Include the first line of any log message\n" + " and some details about the contents of the change, unless '-q' is\n" + " given.\n" + "\n" + " Any conflict between the change being unshelved and a change\n" + " already in the WC is handled the same way as by 'svn patch',\n" + " creating a 'reject' file.\n" + "\n" + " The shelving feature is EXPERIMENTAL. This command is likely to change\n" + " in the next release, and there is no promise of backward compatibility.\n" + ), + {opt_keep_shelved, opt_list, 'q', opt_dry_run} }, + + { "shelves", svn_cl__shelves, {0}, N_ + ("List shelved changes.\n" + "usage: shelves\n" + "\n" + " The shelving feature is EXPERIMENTAL. This command is likely to change\n" + " in the next release, and there is no promise of backward compatibility.\n" + ), + }, + { "status", svn_cl__status, {"stat", "st"}, N_ ("Print the status of working copy files and directories.\n" "usage: status [PATH...]\n" @@ -2044,6 +2154,7 @@ sub_main(int *exit_code, int argc, const apr_hash_t *changelists; apr_hash_t *cfg_hash; svn_membuf_t buf; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -2282,6 +2393,9 @@ sub_main(int *exit_code, int argc, const case opt_dry_run: opt_state.dry_run = TRUE; break; + case opt_list: + opt_state.list = TRUE; + break; case opt_revprop: opt_state.revprop = TRUE; break; @@ -2336,6 +2450,9 @@ sub_main(int *exit_code, int argc, const SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_encoding: opt_state.encoding = apr_pstrdup(pool, opt_arg); break; @@ -2462,6 +2579,7 @@ sub_main(int *exit_code, int argc, const opt_state.diff.summarize = TRUE; break; case opt_remove: + case opt_delete: opt_state.remove = TRUE; break; case opt_changelist: @@ -2477,6 +2595,7 @@ sub_main(int *exit_code, int argc, const opt_state.keep_changelists = TRUE; break; case opt_keep_local: + case opt_keep_shelved: opt_state.keep_local = TRUE; break; case opt_with_all_revprops: @@ -2833,6 +2952,14 @@ sub_main(int *exit_code, int argc, const "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !opt_state.non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + /* Disallow simultaneous use of both --diff-cmd and --internal-diff. */ if (opt_state.diff.diff_cmd && opt_state.diff.internal_diff) @@ -2984,7 +3111,8 @@ sub_main(int *exit_code, int argc, const || subcommand->cmd_func == svn_cl__mkdir || subcommand->cmd_func == svn_cl__move || subcommand->cmd_func == svn_cl__lock - || subcommand->cmd_func == svn_cl__propedit)) + || subcommand->cmd_func == svn_cl__propedit + || subcommand->cmd_func == svn_cl__shelve)) { /* If the -F argument is a file that's under revision control, that's probably not what the user intended. */ @@ -3122,6 +3250,12 @@ sub_main(int *exit_code, int argc, const conflict_stats, pool)); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&opt_state.auth_password, pool, pool)); + } + /* Set up our cancellation support. */ svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; Modified: subversion/branches/better-pristines/subversion/svn/util.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svn/util.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svn/util.c (original) +++ subversion/branches/better-pristines/subversion/svn/util.c Tue Jan 2 19:52:28 2018 @@ -614,6 +614,7 @@ svn_cl__try(svn_error_t *err, if (! quiet) svn_handle_warning2(stderr, err, "svn: "); svn_error_clear(err); + va_end(ap); return SVN_NO_ERROR; } } Modified: subversion/branches/better-pristines/subversion/svnadmin/svnadmin.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svnadmin/svnadmin.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svnadmin/svnadmin.c (original) +++ subversion/branches/better-pristines/subversion/svnadmin/svnadmin.c Tue Jan 2 19:52:28 2018 @@ -1646,8 +1646,8 @@ subcommand_load(apr_getopt_t *os, void * opt_state->use_pre_commit_hook, opt_state->use_post_commit_hook, !opt_state->bypass_prop_validation, - opt_state->normalize_props, opt_state->ignore_dates, + opt_state->normalize_props, opt_state->quiet ? NULL : repos_notify_handler, feedback_stream, check_cancel, NULL, pool); @@ -1703,8 +1703,8 @@ subcommand_load_revprops(apr_getopt_t *o err = svn_repos_load_fs_revprops(repos, in_stream, lower, upper, !opt_state->bypass_prop_validation, - opt_state->normalize_props, opt_state->ignore_dates, + opt_state->normalize_props, opt_state->quiet ? NULL : repos_notify_handler, feedback_stream, check_cancel, NULL, pool); Modified: subversion/branches/better-pristines/subversion/svnbench/svnbench.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svnbench/svnbench.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svnbench/svnbench.c (original) +++ subversion/branches/better-pristines/subversion/svnbench/svnbench.c Tue Jan 2 19:52:28 2018 @@ -53,6 +53,7 @@ use the short option letter as identifier. */ typedef enum svn_cl__longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_config_dir, opt_config_options, @@ -112,6 +113,8 @@ const apr_getopt_option_t svn_cl__option {"verbose", 'v', 0, N_("print extra information")}, {"username", opt_auth_username, 1, N_("specify a username ARG")}, {"password", opt_auth_password, 1, N_("specify a password ARG")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, N_("read password from stdin")}, {"targets", opt_targets, 1, N_("pass contents of file ARG as additional args")}, {"depth", opt_depth, 1, @@ -197,7 +200,8 @@ const apr_getopt_option_t svn_cl__option command to take these arguments allows scripts to just pass them 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_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_no_auth_cache, opt_non_interactive, opt_trust_server_cert, opt_trust_server_cert_failures, opt_config_dir, opt_config_options, 0 }; @@ -394,6 +398,7 @@ sub_main(int *exit_code, int argc, const apr_time_t start_time, time_taken; ra_progress_baton_t ra_progress_baton = {0}; svn_membuf_t buf; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -625,6 +630,9 @@ sub_main(int *exit_code, int argc, const SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_stop_on_copy: opt_state.stop_on_copy = TRUE; break; @@ -842,6 +850,14 @@ sub_main(int *exit_code, int argc, const "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !opt_state.non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + /* Ensure that 'revision_ranges' has at least one item, and make 'start_revision' and 'end_revision' match that item. */ if (opt_state.revision_ranges->nelts == 0) @@ -919,6 +935,12 @@ sub_main(int *exit_code, int argc, const pool)); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&opt_state.auth_password, pool, pool)); + } + /* Set up our cancellation support. */ svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; Modified: subversion/branches/better-pristines/subversion/svnfsfs/load-index-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svnfsfs/load-index-cmd.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svnfsfs/load-index-cmd.c (original) +++ subversion/branches/better-pristines/subversion/svnfsfs/load-index-cmd.c Tue Jan 2 19:52:28 2018 @@ -147,7 +147,7 @@ load_index(const char *path, /* Get the next line from the input and stop if there is none. */ svn_pool_clear(iterpool); - svn_stream_readline(input, &line, "\n", &eol, iterpool); + SVN_ERR(svn_stream_readline(input, &line, "\n", &eol, iterpool)); if (eol) break; Modified: subversion/branches/better-pristines/subversion/svnmucc/svnmucc.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svnmucc/svnmucc.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svnmucc/svnmucc.c (original) +++ subversion/branches/better-pristines/subversion/svnmucc/svnmucc.c Tue Jan 2 19:52:28 2018 @@ -297,6 +297,7 @@ help(FILE *stream, apr_pool_t *pool) " -F [--file] ARG : read log message from file ARG\n" " -u [--username] ARG : commit the changes as username ARG\n" " -p [--password] ARG : use ARG as the password\n" + " --password-from-stdin : read password from stdin\n" " -U [--root-url] ARG : interpret all action URLs relative to ARG\n" " -r [--revision] ARG : use revision ARG as baseline for changes\n" " --with-revprop ARG : set revision property in the following format:\n" @@ -480,13 +481,15 @@ sub_main(int *exit_code, int argc, const non_interactive_opt, force_interactive_opt, trust_server_cert_opt, - trust_server_cert_failures_opt + trust_server_cert_failures_opt, + password_from_stdin_opt }; static const apr_getopt_option_t options[] = { {"message", 'm', 1, ""}, {"file", 'F', 1, ""}, {"username", 'u', 1, ""}, {"password", 'p', 1, ""}, + {"password-from-stdin", password_from_stdin_opt, 0, ""}, {"root-url", 'U', 1, ""}, {"revision", 'r', 1, ""}, {"with-revprop", with_revprop_opt, 1, ""}, @@ -527,6 +530,7 @@ sub_main(int *exit_code, int argc, const svn_client_ctx_t *ctx; struct log_message_baton lmb; int i; + svn_boolean_t read_pass_from_stdin = FALSE; /* Check library versions */ SVN_ERR(check_lib_versions()); @@ -572,6 +576,9 @@ sub_main(int *exit_code, int argc, const case 'p': password = apr_pstrdup(pool, arg); break; + case password_from_stdin_opt: + read_pass_from_stdin = TRUE; + break; case 'U': SVN_ERR(svn_utf_cstring_to_utf8(&root_url, arg, pool)); if (! svn_path_is_url(root_url)) @@ -672,6 +679,15 @@ sub_main(int *exit_code, int argc, const "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + + /* Copy the rest of our command-line arguments to an array, UTF-8-ing them along the way. */ action_args = apr_array_make(pool, opts->argc, sizeof(const char *)); @@ -721,6 +737,12 @@ sub_main(int *exit_code, int argc, const "svnmucc: ", "--config-option")); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&password, pool, pool)); + } + SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG); Modified: subversion/branches/better-pristines/subversion/svnrdump/svnrdump.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svnrdump/svnrdump.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svnrdump/svnrdump.c (original) +++ subversion/branches/better-pristines/subversion/svnrdump/svnrdump.c Tue Jan 2 19:52:28 2018 @@ -59,6 +59,7 @@ enum svn_svnrdump__longopt_t opt_config_option, opt_auth_username, opt_auth_password, + opt_auth_password_from_stdin, opt_auth_nocache, opt_non_interactive, opt_skip_revprop, @@ -73,6 +74,7 @@ enum svn_svnrdump__longopt_t opt_config_option, \ opt_auth_username, \ opt_auth_password, \ + opt_auth_password_from_stdin, \ opt_auth_nocache, \ opt_trust_server_cert, \ opt_trust_server_cert_failures, \ @@ -114,6 +116,8 @@ static const apr_getopt_option_t svnrdum N_("specify a username ARG")}, {"password", opt_auth_password, 1, N_("specify a password ARG")}, + {"password-from-stdin", opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"non-interactive", opt_non_interactive, 0, N_("do no interactive prompting (default is to prompt\n" " " @@ -154,6 +158,7 @@ static const apr_getopt_option_t svnrdum "valid certificate) and 'other' (all other not\n" " " "separately classified certificate errors).")}, + {"dumpfile", 'F', 1, N_("Read or write to a dumpfile instead of stdin/stdout")}, {0, 0, 0, 0} }; @@ -174,6 +179,7 @@ typedef struct opt_baton_t { svn_client_ctx_t *ctx; svn_ra_session_t *session; const char *url; + const char *dumpfile; svn_boolean_t help; svn_boolean_t version; svn_opt_revision_t start_revision; @@ -463,31 +469,39 @@ replay_revisions(svn_ra_session_t *sessi svn_revnum_t end_revision, svn_boolean_t quiet, svn_boolean_t incremental, + const char *dumpfile, apr_pool_t *pool) { struct replay_baton *replay_baton; const char *uuid; - svn_stream_t *stdout_stream; + svn_stream_t *output_stream; - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); + if (dumpfile) + { + SVN_ERR(svn_stream_open_writable(&output_stream, dumpfile, pool, pool)); + } + else + { + SVN_ERR(svn_stream_for_stdout(&output_stream, pool)); + } replay_baton = apr_pcalloc(pool, sizeof(*replay_baton)); - replay_baton->stdout_stream = stdout_stream; + replay_baton->stdout_stream = output_stream; replay_baton->extra_ra_session = extra_ra_session; replay_baton->quiet = quiet; /* Write the magic header and UUID */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(output_stream, pool, SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", SVN_REPOS_DUMPFILE_FORMAT_VERSION)); SVN_ERR(svn_ra_get_uuid2(session, &uuid, pool)); - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(output_stream, pool, SVN_REPOS_DUMPFILE_UUID ": %s\n\n", uuid)); /* Fake revision 0 if necessary */ if (start_revision == 0) { - SVN_ERR(dump_revision_header(session, stdout_stream, + SVN_ERR(dump_revision_header(session, output_stream, start_revision, pool)); /* Revision 0 has no tree changes, so we're done. */ @@ -506,7 +520,7 @@ replay_revisions(svn_ra_session_t *sessi if (!incremental) { SVN_ERR(dump_initial_full_revision(session, extra_ra_session, - stdout_stream, start_revision, + output_stream, start_revision, quiet, pool)); start_revision++; } @@ -538,16 +552,23 @@ replay_revisions(svn_ra_session_t *sessi static svn_error_t * load_revisions(svn_ra_session_t *session, svn_ra_session_t *aux_session, - const char *url, + const char *dumpfile, svn_boolean_t quiet, apr_hash_t *skip_revprops, apr_pool_t *pool) { - svn_stream_t *stdin_stream; + svn_stream_t *output_stream; - SVN_ERR(svn_stream_for_stdin2(&stdin_stream, TRUE, pool)); + if (dumpfile) + { + SVN_ERR(svn_stream_open_readonly(&output_stream, dumpfile, pool, pool)); + } + else + { + SVN_ERR(svn_stream_for_stdin2(&output_stream, TRUE, pool)); + } - SVN_ERR(svn_rdump__load_dumpstream(stdin_stream, session, aux_session, + SVN_ERR(svn_rdump__load_dumpstream(output_stream, session, aux_session, quiet, skip_revprops, check_cancel, NULL, pool)); @@ -616,7 +637,8 @@ dump_cmd(apr_getopt_t *os, return replay_revisions(opt_baton->session, extra_ra_session, opt_baton->start_revision.value.number, opt_baton->end_revision.value.number, - opt_baton->quiet, opt_baton->incremental, pool); + opt_baton->quiet, opt_baton->incremental, + opt_baton->dumpfile, pool); } /* Handle the "load" subcommand. Implements `svn_opt_subcommand_t'. */ @@ -630,8 +652,9 @@ load_cmd(apr_getopt_t *os, SVN_ERR(svn_client_open_ra_session2(&aux_session, opt_baton->url, NULL, opt_baton->ctx, pool, pool)); - return load_revisions(opt_baton->session, aux_session, opt_baton->url, - opt_baton->quiet, opt_baton->skip_revprops, pool); + return load_revisions(opt_baton->session, aux_session, + opt_baton->dumpfile, opt_baton->quiet, + opt_baton->skip_revprops, pool); } /* Handle the "help" subcommand. Implements `svn_opt_subcommand_t'. */ @@ -772,12 +795,14 @@ sub_main(int *exit_code, int argc, const apr_getopt_t *os; apr_array_header_t *received_opts; int i; + svn_boolean_t read_pass_from_stdin = FALSE; 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; opt_baton->skip_revprops = apr_hash_make(pool); + opt_baton->dumpfile = NULL; SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); @@ -850,6 +875,9 @@ sub_main(int *exit_code, int argc, const case opt_auth_password: SVN_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_auth_nocache: no_auth_cache = TRUE; break; @@ -890,6 +918,11 @@ sub_main(int *exit_code, int argc, const opt_arg, "svnrdump: ", pool)); + break; + case 'F': + SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool)); + opt_baton->dumpfile = opt_arg; + break; } } @@ -1005,6 +1038,24 @@ sub_main(int *exit_code, int argc, const "--non-interactive")); } + if (read_pass_from_stdin && !non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + + if (strcmp(subcommand->name, "load") == 0) + { + if (read_pass_from_stdin && opt_baton->dumpfile == NULL) + { + /* error here, since load cannot process a password over stdin */ + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("load subcommand with " + "--password-from-stdin requires -F")); + } + } + /* Expect one more non-option argument: the repository URL. */ if (os->ind != os->argc - 1) { @@ -1039,6 +1090,12 @@ sub_main(int *exit_code, int argc, const force_interactive = (username == NULL || password == NULL); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_io_stdin_readline(&password, pool, pool)); + } + non_interactive = !svn_cmdline__be_interactive(non_interactive, force_interactive); Modified: subversion/branches/better-pristines/subversion/svnserve/serve.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/svnserve/serve.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/svnserve/serve.c (original) +++ subversion/branches/better-pristines/subversion/svnserve/serve.c Tue Jan 2 19:52:28 2018 @@ -2821,17 +2821,9 @@ static svn_error_t *file_rev_handler(voi svn_stream_set_write(stream, svndiff_handler); svn_stream_set_close(stream, svndiff_close_handler); - /* If the connection does not support SVNDIFF1 or if we don't want to use - * compression, use the non-compressing "version 0" implementation */ - /* ### TODO: Check SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED and decide between - * ### svndiff1[at compression_level] and svndiff2 */ - if ( svn_ra_svn_compression_level(frb->conn) > 0 - && svn_ra_svn_has_capability(frb->conn, SVN_RA_SVN_CAP_SVNDIFF1)) - svn_txdelta_to_svndiff3(d_handler, d_baton, stream, 1, - svn_ra_svn_compression_level(frb->conn), pool); - else - svn_txdelta_to_svndiff3(d_handler, d_baton, stream, 0, - svn_ra_svn_compression_level(frb->conn), pool); + svn_txdelta_to_svndiff3(d_handler, d_baton, stream, + svn_ra_svn__svndiff_version(frb->conn), + svn_ra_svn_compression_level(frb->conn), pool); } else SVN_ERR(svn_ra_svn__write_cstring(frb->conn, pool, "")); Modified: subversion/branches/better-pristines/subversion/tests/cmdline/basic_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/basic_tests.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/basic_tests.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/basic_tests.py Tue Jan 2 19:52:28 2018 @@ -3114,7 +3114,7 @@ def plaintext_password_storage_disabled( f.close() - +@Skip(svntest.main.is_os_windows) def filtered_ls(sbox): "filtered 'svn ls'" @@ -3140,6 +3140,64 @@ def filtered_ls(sbox): exit_code, output, error = svntest.actions.run_and_verify_svn( [], [], 'ls', path, '--depth=infinity', '--search=*/*') +@Issue(4700) +@XFail(svntest.main.is_fs_type_fsx) +def null_update_last_changed_revision(sbox): + "null 'update' updates last changed rev" + + sbox.build() + wc_dir = sbox.wc_dir + + # r2: Random text change. + old_contents = open(sbox.path("iota")).read() + sbox.simple_append("iota", "Line 2.\n") + sbox.simple_commit(message='r2') + sbox.simple_update() + + # r3: Revert r2. + sbox.simple_append("iota", old_contents, truncate=True) + sbox.simple_commit(message='r3') + sbox.simple_update() + + # Perform a null update. + # + # This used to say '3'; probably because iota@3 and iota@1 were textually + # identical. It seems this problem was introduced in r1760570. + sbox.simple_update(revision='1') + svntest.actions.run_and_verify_svn(["1\n"], [], + 'info', sbox.path('iota'), + '--show-item', 'last-changed-revision') + +@Issue(4700) +@XFail(svntest.main.is_fs_type_bdb) +@XFail(svntest.main.is_fs_type_fsx) +def null_prop_update_last_changed_revision(sbox): + "null 'property update' updates last changed rev" + + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_propset("prop", "value", "iota") + sbox.simple_commit(message='r2') + sbox.simple_update() + + # r3: change the property + sbox.simple_propset("prop", "changed", "iota") + sbox.simple_commit(message='r3') + sbox.simple_update() + + # r4: Revert r3. + sbox.simple_propset("prop", "value", "iota") + sbox.simple_commit(message='r4') + sbox.simple_update() + + # Perform a null update. + sbox.simple_update(revision='2') + svntest.actions.run_and_verify_svn(["2\n"], [], + 'info', sbox.path('iota'), + '--show-item', 'last-changed-revision') + + ######################################################################## # Run the tests @@ -3211,6 +3269,8 @@ test_list = [ None, mkdir_parents_target_exists_on_disk, plaintext_password_storage_disabled, filtered_ls, + null_update_last_changed_revision, + null_prop_update_last_changed_revision, ] if __name__ == '__main__': Modified: subversion/branches/better-pristines/subversion/tests/cmdline/diff_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/diff_tests.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/diff_tests.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/diff_tests.py Tue Jan 2 19:52:28 2018 @@ -5140,6 +5140,26 @@ def diff_peg_resolve(sbox): repo_url + '/branches/A2', wc_dir, '-r1:2') +@XFail() +@Issue(4706) +def diff_unversioned_files_git(sbox): + "diff unversioned files in git format" + sbox.build() + wc_dir = sbox.wc_dir + + svntest.main.file_write(sbox.ospath('foo'), "foo\n") + svntest.main.file_write(sbox.ospath('A/bar'), "bar\n") + expected_output = make_diff_header("foo", "working copy", "working copy", + "foo", "A/bar") + [ + "@@ -1 +1 @@\n", + "-foo\n", + "+bar\n" + ] + svntest.actions.run_and_verify_svn(expected_output, [], + 'diff', '--git', + '--old', sbox.ospath('foo'), + '--new', sbox.ospath('A/bar')) + ######################################################################## #Run the tests @@ -5236,6 +5256,7 @@ test_list = [ None, diff_incomplete_props, diff_symlinks, diff_peg_resolve, + diff_unversioned_files_git, ] if __name__ == '__main__': Modified: subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout Tue Jan 2 19:52:28 2018 @@ -42,6 +42,9 @@ Available subcommands: resolve resolved revert + shelve + unshelve + shelves status (stat, st) switch (sw) unlock Modified: subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Tue Jan 2 19:52:28 2018 @@ -127,13 +127,15 @@ Valid options: -U ARG, --context ARG: Show ARG lines of context -p, --show-c-function: Show C function name --search ARG : use ARG as search pattern (glob syntax, case- - and accent-insensitive) + and accent-insensitive, may require quotation marks + to prevent shell expansion) --search-and ARG : combine ARG with the previous search pattern Global options: --username ARG : specify a username ARG --password ARG : specify a password ARG (caution: on many operating systems, other users will be able to see this) + --password-from-stdin : read password from stdin --no-auth-cache : do not cache authentication tokens --non-interactive : do no interactive prompting (default is to prompt only if standard input is a terminal device) @@ -224,6 +226,7 @@ Global options: --username ARG : specify a username ARG --password ARG : specify a password ARG (caution: on many operating systems, other users will be able to see this) + --password-from-stdin : read password from stdin --no-auth-cache : do not cache authentication tokens --non-interactive : do no interactive prompting (default is to prompt only if standard input is a terminal device) Modified: subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout Tue Jan 2 19:52:28 2018 @@ -42,6 +42,9 @@ Available subcommands: resolve resolved revert + shelve + unshelve + shelves status (stat, st) switch (sw) unlock Modified: subversion/branches/better-pristines/subversion/tests/cmdline/svnadmin_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/svnadmin_tests.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/svnadmin_tests.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/svnadmin_tests.py Tue Jan 2 19:52:28 2018 @@ -129,6 +129,15 @@ def check_hotcopy_fsfs_fsx(src, dst): if src_file == 'rep-cache.db': db1 = svntest.sqlite3.connect(src_path) db2 = svntest.sqlite3.connect(dst_path) + schema1 = db1.execute("pragma user_version").fetchone()[0] + schema2 = db2.execute("pragma user_version").fetchone()[0] + if schema1 != schema2: + raise svntest.Failure("rep-cache schema differs: '%s' vs. '%s'" + % (schema1, schema2)) + # Can't test newer rep-cache schemas with an old built-in SQLite. + if schema1 >= 2 and svntest.sqlite3.sqlite_version_info < (3, 8, 2): + continue + rows1 = [] rows2 = [] for row in db1.execute("select * from rep_cache order by hash"): @@ -746,7 +755,7 @@ def verify_windows_paths_in_repos(sbox): "* Verified revision 0.\n", "* Verified revision 1.\n", "* Verified revision 2.\n"], output) - elif svntest.main.fs_has_rep_sharing(): + elif svntest.main.fs_has_rep_sharing() and not svntest.main.is_fs_type_bdb(): svntest.verify.compare_and_display_lines( "Error while running 'svnadmin verify'.", 'STDOUT', ["* Verifying repository metadata ...\n", @@ -790,6 +799,10 @@ def fsfs_file(repo_dir, kind, rev): def verify_incremental_fsfs(sbox): """svnadmin verify detects corruption dump can't""" + if svntest.main.options.fsfs_version is not None and \ + svntest.main.options.fsfs_version not in [4, 6]: + raise svntest.Skip("Unsupported prepackaged repository version") + # setup a repo with a directory 'c:hi' # use physical addressing as this is hard to provoke with logical addressing sbox.build(create_wc = False, @@ -807,7 +820,7 @@ def verify_incremental_fsfs(sbox): # the listing itself is valid. r2 = fsfs_file(sbox.repo_dir, 'revs', '2') if r2.endswith('pack'): - raise svntest.Skip('Test doesn\'t handle packed revisions') + raise svntest.Skip("Test doesn't handle packed revisions") fp = open(r2, 'wb') fp.write(b"""id: 0-2.0.r2/0 @@ -1654,6 +1667,10 @@ text def verify_non_utf8_paths(sbox): "svnadmin verify with non-UTF-8 paths" + if svntest.main.options.fsfs_version is not None and \ + svntest.main.options.fsfs_version not in [4, 6]: + raise svntest.Skip("Unsupported prepackaged repository version") + dumpfile = clean_dumpfile() # Corruption only possible in physically addressed revisions created @@ -1676,15 +1693,12 @@ def verify_non_utf8_paths(sbox): if line == b"A\n": # replace 'A' with a latin1 character -- the new path is not valid UTF-8 fp_new.write(b"\xE6\n") - elif line == b"text: 1 279 32 32 d63ecce65d8c428b86f4f8b0920921fe\n": + elif line == b"text: 1 340 32 32 a6be7b4cf075fd39e6a99eb69a31232b\n": # phys, PLAIN directories: fix up the representation checksum - fp_new.write(b"text: 1 279 32 32 b50b1d5ed64075b5f632f3b8c30cd6b2\n") - elif line == b"text: 1 292 44 32 a6be7b4cf075fd39e6a99eb69a31232b\n": + fp_new.write(b"text: 1 340 32 32 f2e93e73272cac0f18fccf16f224eb93\n") + elif line == b"text: 1 340 44 32 a6be7b4cf075fd39e6a99eb69a31232b\n": # phys, deltified directories: fix up the representation checksum - fp_new.write(b"text: 1 292 44 32 f2e93e73272cac0f18fccf16f224eb93\n") - elif line == b"text: 1 6 31 31 90f306aa9bfd72f456072076a2bd94f7\n": - # log addressing: fix up the representation checksum - fp_new.write(b"text: 1 6 31 31 db2d4a0bad5dff0aea9a288dec02f1fb\n") + fp_new.write(b"text: 1 340 44 32 f2e93e73272cac0f18fccf16f224eb93\n") elif line == b"cpath: /A\n": # also fix up the 'created path' field fp_new.write(b"cpath: /\xE6\n") @@ -2520,7 +2534,7 @@ def verify_denormalized_names(sbox): ".*Verified revision 7."] # The BDB backend doesn't do global metadata verification. - if (svntest.main.fs_has_rep_sharing()): + if (svntest.main.fs_has_rep_sharing() and not svntest.main.is_fs_type_bdb()): expected_output_regex_list.insert(0, ".*Verifying repository metadata.*") if svntest.main.options.fsfs_sharding is not None: @@ -3350,7 +3364,8 @@ def dump_no_op_change(sbox): svntest.actions.run_and_verify_svn(expected, [], 'log', '-v', sbox2.repo_url + '/bar') -@XFail() # This test will XPASS on FSFS if rep-caching is disabled. +@XFail(svntest.main.is_fs_type_bdb) +@XFail(svntest.main.is_fs_type_fsx) @Issue(4623) def dump_no_op_prop_change(sbox): "svnadmin dump with no-op property change" Modified: subversion/branches/better-pristines/subversion/tests/cmdline/svntest/__init__.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/svntest/__init__.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/svntest/__init__.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/svntest/__init__.py Tue Jan 2 19:52:28 2018 @@ -35,11 +35,8 @@ if sys.hexversion < 0x2070000: try: import sqlite3 except ImportError: - try: - from pysqlite2 import dbapi2 as sqlite3 - except ImportError: - sys.stderr.write('[SKIPPED] Python sqlite3 module required\n') - sys.exit(0) + sys.stderr.write('[SKIPPED] Python sqlite3 module required\n') + sys.exit(0) # don't export this name del sys Modified: subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/svntest/main.py Tue Jan 2 19:52:28 2018 @@ -56,7 +56,7 @@ import svntest from svntest import Failure from svntest import Skip -SVN_VER_MINOR = 10 +SVN_VER_MINOR = 11 ###################################################################### # @@ -1043,7 +1043,8 @@ def _post_create_repos(path, minor_versi shutil.copy(options.config_file, confpath) if options.memcached_server is not None or \ - options.fsfs_compression is not None and \ + options.fsfs_compression is not None or \ + options.fsfs_dir_deltification is not None and \ os.path.exists(confpath): with open(confpath, 'r') as conffile: newlines = [] @@ -1051,6 +1052,10 @@ def _post_create_repos(path, minor_versi if line.startswith('# compression ') and \ options.fsfs_compression is not None: line = 'compression = %s\n' % options.fsfs_compression + if line.startswith('# enable-dir-deltification ') and \ + options.fsfs_dir_deltification is not None: + line = 'enable-dir-deltification = %s\n' % \ + options.fsfs_dir_deltification newlines += line if options.memcached_server is not None and \ line == '[memcached-servers]\n': @@ -1569,9 +1574,11 @@ def is_fs_log_addressing(): return is_fs_type_fsx() or \ (is_fs_type_fsfs() and options.server_minor_version >= 9) +def fs_has_sha1(): + return fs_has_rep_sharing() + def fs_has_rep_sharing(): - return is_fs_type_fsx() or \ - (is_fs_type_fsfs() and options.server_minor_version >= 6) + return options.server_minor_version >= 6 def fs_has_pack(): return is_fs_type_fsx() or \ @@ -1603,28 +1610,28 @@ def server_has_mergeinfo(): return options.server_minor_version >= 5 def server_has_revprop_commit(): - return options.server_minor_version >= 5 + return options.server_caps.has_revprop_commit def server_authz_has_aliases(): - return options.server_minor_version >= 5 + return options.server_caps.authz_has_aliases def server_gets_client_capabilities(): - return options.server_minor_version >= 5 + return options.server_caps.gets_client_capabilities def server_has_partial_replay(): - return options.server_minor_version >= 5 + return options.server_caps.has_partial_replay def server_enforces_UTF8_fspaths_in_verify(): - return options.server_minor_version >= 6 + return options.server_caps.enforces_UTF8_fspaths_in_verify def server_enforces_date_syntax(): - return options.server_minor_version >= 5 + return options.server_caps.enforces_date_syntax def server_has_atomic_revprop(): - return options.server_minor_version >= 7 + return options.server_caps.has_atomic_revprop def server_has_reverse_get_file_revs(): - return options.server_minor_version >= 8 + return options.server_caps.has_reverse_get_file_revs def is_plaintext_password_storage_disabled(): try: @@ -1739,6 +1746,8 @@ class TestSpawningThread(threading.Threa args.append('--dump-load-cross-check') if options.fsfs_compression: args.append('--fsfs-compression=' + options.fsfs_compression) + if options.fsfs_dir_deltification: + args.append('--fsfs-dir-deltification=' + options.fsfs_dir_deltification) result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None, *args) @@ -2153,6 +2162,8 @@ def _create_parser(usage=None): help='Use memcached server at specified URL (FSFS only)') parser.add_option('--fsfs-compression', action='store', type='str', help='Set compression type (for fsfs)') + parser.add_option('--fsfs-dir-deltification', action='store', type='str', + help='Set directory deltification option (for fsfs)') # most of the defaults are None, but some are other values, set them here parser.set_defaults( @@ -2165,6 +2176,19 @@ def _create_parser(usage=None): return parser +class ServerCaps(): + """A simple struct that contains the actual server capabilities that don't + depend on other settings like FS versions.""" + + def __init__(self, options): + self.has_revprop_commit = options.server_minor_version >= 5 + self.authz_has_aliases = options.server_minor_version >= 5 + self.gets_client_capabilities = options.server_minor_version >= 5 + self.has_partial_replay = options.server_minor_version >= 5 + self.enforces_UTF8_fspaths_in_verify = options.server_minor_version >= 6 + self.enforces_date_syntax = options.server_minor_version >= 5 + self.has_atomic_revprop = options.server_minor_version >= 7 + self.has_reverse_get_file_revs = options.server_minor_version >= 8 def parse_options(arglist=sys.argv[1:], usage=None): """Parse the arguments in arg_list, and set the global options object with @@ -2175,6 +2199,12 @@ def parse_options(arglist=sys.argv[1:], parser = _create_parser(usage) (options, args) = parser.parse_args(arglist) + # Peg the actual server capabilities. + # We tweak the server_minor_version later to accommodate FS restrictions, + # but we don't want them to interfere with expectations towards the "pure" + # server code. + options.server_caps = ServerCaps(options) + # If there are no logging handlers registered yet, then install our # own with our custom formatter. (anything currently installed *is* # our handler as tested above, in _create_parser) @@ -2206,26 +2236,29 @@ def parse_options(arglist=sys.argv[1:], parser.error("test harness only supports server minor versions 3-%d" % SVN_VER_MINOR) - # Make sure the server-minor-version matches the fsfs-version parameter. + pass + + return (parser, args) + +def tweak_options_for_precooked_repos(): + """Make sure the server-minor-version matches the fsfs-version parameter + for pre-cooked repositories.""" + + global options + + # Server versions that introduced the respective FSFS formats: + introducing_version = { 1:1, 2:4, 3:5, 4:6, 6:8, 7:9 } if options.fsfs_version: - if options.fsfs_version == 6: + if options.fsfs_version in introducing_version: + introduced_in = introducing_version[options.fsfs_version] if options.server_minor_version \ - and options.server_minor_version != 8 \ + and options.server_minor_version != introduced_in \ and options.server_minor_version != SVN_VER_MINOR: - parser.error("--fsfs-version=6 requires --server-minor-version=8") - options.server_minor_version = 8 - if options.fsfs_version == 4: - if options.server_minor_version \ - and options.server_minor_version != 7 \ - and options.server_minor_version != SVN_VER_MINOR: - parser.error("--fsfs-version=4 requires --server-minor-version=7") - options.server_minor_version = 7 - pass + parser.error("--fsfs-version=%d requires --server-minor-version=%d" \ + % (options.fsfs_version, introduced_in)) + options.server_minor_version = introduced_in # ### Add more tweaks here if and when we support pre-cooked versions # ### of FSFS repositories. - pass - - return (parser, args) def run_tests(test_list, serial_only = False): @@ -2321,6 +2354,7 @@ def execute_tests(test_list, serial_only if not options: # Override which tests to run from the commandline (parser, args) = parse_options() + tweak_options_for_precooked_repos() test_selection = args else: parser = _create_parser() Modified: subversion/branches/better-pristines/subversion/tests/cmdline/svntest/verify.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/svntest/verify.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/svntest/verify.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/svntest/verify.py Tue Jan 2 19:52:28 2018 @@ -467,10 +467,11 @@ def verify_exit_code(message, actual, ex # A simple dump file parser. While sufficient for the current # testsuite it doesn't cope with all valid dump files. class DumpParser: - def __init__(self, lines): + def __init__(self, lines, ignore_sha1=False): self.current = 0 self.lines = lines self.parsed = {} + self.ignore_sha1 = ignore_sha1 def parse_line(self, regex, required=True): m = re.match(regex, self.lines[self.current]) @@ -660,6 +661,9 @@ class DumpParser: if not header in headers: node[key] = None continue + if self.ignore_sha1 and (key in ['copy_sha1', 'text_sha1']): + node[key] = None + continue m = re.match(regex, headers[header]) if not m: raise SVNDumpParseError("expected '%s' at line %d\n%s" @@ -735,8 +739,7 @@ def compare_dump_files(message, label, e of lines as returned by run_and_verify_dump, and check that the same revisions, nodes, properties, etc. are present in both dumps. """ - - parsed_expected = DumpParser(expected).parse() + parsed_expected = DumpParser(expected, not svntest.main.fs_has_sha1()).parse() parsed_actual = DumpParser(actual).parse() if ignore_uuid: Modified: subversion/branches/better-pristines/subversion/tests/cmdline/svntest/wc.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/svntest/wc.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/svntest/wc.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/svntest/wc.py Tue Jan 2 19:52:28 2018 @@ -1092,17 +1092,8 @@ def svn_uri_quote(url): def python_sqlite_can_read_wc(): """Check if the Python builtin is capable enough to peek into wc.db""" - - try: - db = svntest.sqlite3.connect('') - - c = db.cursor() - c.execute('select sqlite_version()') - ver = tuple(map(int, c.fetchall()[0][0].split('.'))) - - return ver >= (3, 6, 18) # Currently enough (1.7-1.9) - except: - return False + # Currently enough (1.7-1.9) + return svntest.sqlite3.sqlite_version_info >= (3, 6, 18) def open_wc_db(local_path): """Open the SQLite DB for the WC path LOCAL_PATH. Modified: subversion/branches/better-pristines/subversion/tests/cmdline/update_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/cmdline/update_tests.py?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/cmdline/update_tests.py (original) +++ subversion/branches/better-pristines/subversion/tests/cmdline/update_tests.py Tue Jan 2 19:52:28 2018 @@ -6840,6 +6840,21 @@ def update_delete_switched(sbox): svntest.actions.run_and_verify_update(wc_dir, None, None, expected_status, [], False, sbox.ospath('A'), '-r', 0) +@XFail() +def update_add_missing_local_add(sbox): + "update adds missing local addition" + + sbox.build(read_only=True) + + # Note that updating 'A' to r0 doesn't reproduce this issue... + sbox.simple_update('', revision='0') + sbox.simple_mkdir('A') + sbox.simple_add_text('mumumu', 'A/mu') + os.unlink(sbox.ospath('A/mu')) + os.rmdir(sbox.ospath('A')) + + sbox.simple_update() + ####################################################################### # Run the tests @@ -6930,6 +6945,7 @@ test_list = [ None, update_add_conflicted_deep, missing_tmp_update, update_delete_switched, + update_add_missing_local_add, ] if __name__ == '__main__': Modified: subversion/branches/better-pristines/subversion/tests/libsvn_client/conflicts-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_client/conflicts-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_client/conflicts-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_client/conflicts-test.c Tue Jan 2 19:52:28 2018 @@ -540,7 +540,7 @@ create_wc_with_dir_add_vs_dir_add_merge_ /* Now move the new directory to the colliding path. */ new_dir_path = svn_relpath_join(trunk_path, new_dir_name, b->pool); SVN_ERR(sbox_wc_update(b, "", SVN_INVALID_REVNUM)); - sbox_wc_move(b, move_src_path, new_dir_path); + SVN_ERR(sbox_wc_move(b, move_src_path, new_dir_path)); SVN_ERR(sbox_wc_commit(b, "")); } new_dir_path = svn_relpath_join(branch_path, new_dir_name, b->pool); Modified: subversion/branches/better-pristines/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c Tue Jan 2 19:52:28 2018 @@ -1631,8 +1631,8 @@ delta_chain_with_plain(const svn_test_op svn_hash_sets(props, "p", svn_string_create(prop_value->data, pool)); hash_rep = svn_stringbuf_create_empty(pool); - svn_hash_write2(props, svn_stream_from_stringbuf(hash_rep, pool), "END", - pool); + SVN_ERR(svn_hash_write2(props, svn_stream_from_stringbuf(hash_rep, pool), + "END", pool)); SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool)); SVN_ERR(svn_fs_txn_root(&root, txn, pool)); Modified: subversion/branches/better-pristines/subversion/tests/libsvn_ra/ra-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_ra/ra-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_ra/ra-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_ra/ra-test.c Tue Jan 2 19:52:28 2018 @@ -427,17 +427,7 @@ lock_cb(void *baton, struct lock_result_t *result = apr_palloc(b->pool, sizeof(struct lock_result_t)); - if (lock) - { - result->lock = apr_palloc(b->pool, sizeof(svn_lock_t)); - *result->lock = *lock; - result->lock->path = apr_pstrdup(b->pool, lock->path); - result->lock->token = apr_pstrdup(b->pool, lock->token); - result->lock->owner = apr_pstrdup(b->pool, lock->owner); - result->lock->comment = apr_pstrdup(b->pool, lock->comment); - } - else - result->lock = NULL; + result->lock = svn_lock_dup(lock, b->pool); result->err = ra_err; svn_hash_sets(b->results, apr_pstrdup(b->pool, path), result); @@ -1682,6 +1672,118 @@ commit_empty_last_change(const svn_test_ return SVN_NO_ERROR; } +static svn_error_t * +commit_locked_file(const svn_test_opts_t *opts, apr_pool_t *pool) +{ + const char *url; + svn_ra_callbacks2_t *cbtable; + svn_ra_session_t *session; + const svn_delta_editor_t *editor; + void *edit_baton; + void *root_baton; + void *file_baton; + struct lock_result_t *lock_result; + apr_hash_t *lock_tokens; + svn_txdelta_window_handler_t handler; + void *handler_baton; + svn_revnum_t fetched_rev; + apr_hash_t *fetched_props; + const svn_string_t *propval; + + SVN_ERR(svn_test__create_repos2(NULL, &url, NULL, + "test-repo-commit-locked-file-test", + opts, pool, pool)); + + SVN_ERR(svn_ra_initialize(pool)); + SVN_ERR(svn_ra_create_callbacks(&cbtable, pool)); + SVN_ERR(svn_test__init_auth_baton(&cbtable->auth_baton, pool)); + + SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable, + NULL, NULL, pool)); + SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton, + apr_hash_make(pool), + NULL, NULL, NULL, TRUE, pool)); + /* Add a file. */ + SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM, + pool, &root_baton)); + SVN_ERR(editor->add_file("file", root_baton, NULL, SVN_INVALID_REVNUM, + pool, &file_baton)); + SVN_ERR(editor->close_file(file_baton, NULL, pool)); + SVN_ERR(editor->close_directory(root_baton, pool)); + SVN_ERR(editor->close_edit(edit_baton, pool)); + + /* Acquire a lock on this file. */ + { + struct lock_baton_t baton = {0}; + svn_revnum_t rev = 1; + apr_hash_t *lock_targets; + + baton.results = apr_hash_make(pool); + baton.pool = pool; + + lock_targets = apr_hash_make(pool); + svn_hash_sets(lock_targets, "file", &rev); + SVN_ERR(svn_ra_lock(session, lock_targets, "comment", FALSE, + lock_cb, &baton, pool)); + + SVN_ERR(expect_lock("file", baton.results, session, pool)); + lock_result = svn_hash_gets(baton.results, "file"); + } + + /* Open a new session using the file parent's URL. */ + SVN_ERR(svn_ra_open4(&session, NULL, url, NULL, cbtable, + NULL, NULL, pool)); + + /* Create a new commit editor supplying our lock token. */ + lock_tokens = apr_hash_make(pool); + svn_hash_sets(lock_tokens, "file", lock_result->lock->token); + SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton, + apr_hash_make(pool), NULL, NULL, + lock_tokens, TRUE, pool)); + /* Edit the locked file. */ + SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM, + pool, &root_baton)); + SVN_ERR(editor->open_file("file", root_baton, SVN_INVALID_REVNUM, pool, + &file_baton)); + SVN_ERR(editor->apply_textdelta(file_baton, NULL, pool, &handler, + &handler_baton)); + SVN_ERR(svn_txdelta_send_string(svn_string_create("A", pool), + handler, handler_baton, pool)); + SVN_ERR(editor->close_file(file_baton, NULL, pool)); + SVN_ERR(editor->close_directory(root_baton, pool)); + SVN_ERR(editor->close_edit(edit_baton, pool)); + + /* Check the result. */ + SVN_ERR(svn_ra_get_file(session, "file", SVN_INVALID_REVNUM, NULL, + &fetched_rev, NULL, pool)); + SVN_TEST_INT_ASSERT((int) fetched_rev, 2); + + /* Change property of the locked file. */ + SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton, + apr_hash_make(pool), NULL, NULL, + lock_tokens, TRUE, pool)); + SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM, + pool, &root_baton)); + SVN_ERR(editor->open_file("file", root_baton, SVN_INVALID_REVNUM, pool, + &file_baton)); + SVN_ERR(editor->change_file_prop(file_baton, "propname", + svn_string_create("propval", pool), + pool)); + SVN_ERR(editor->close_file(file_baton, NULL, pool)); + SVN_ERR(editor->close_directory(root_baton, pool)); + SVN_ERR(editor->close_edit(edit_baton, pool)); + + /* Check the result. */ + SVN_ERR(svn_ra_get_file(session, "file", SVN_INVALID_REVNUM, NULL, + &fetched_rev, &fetched_props, pool)); + SVN_TEST_INT_ASSERT((int) fetched_rev, 3); + propval = svn_hash_gets(fetched_props, "propname"); + SVN_TEST_ASSERT(propval); + SVN_TEST_STRING_ASSERT(propval->data, "propval"); + + return SVN_NO_ERROR; +} + /* The test table. */ @@ -1716,6 +1818,8 @@ static struct svn_test_descriptor_t test "verify checkout over a tunnel"), SVN_TEST_OPTS_PASS(commit_empty_last_change, "check how last change applies to empty commit"), + SVN_TEST_OPTS_PASS(commit_locked_file, + "check commit editor for a locked file"), SVN_TEST_NULL }; Modified: subversion/branches/better-pristines/subversion/tests/libsvn_repos/authz-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_repos/authz-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_repos/authz-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_repos/authz-test.c Tue Jan 2 19:52:28 2018 @@ -277,9 +277,9 @@ test_authz_parse(const svn_test_opts_t * printf("[users]\n"); if (authz->has_anon_rights) - print_user_rights(NULL, NULL, 0, &authz->anon_rights, pool); + SVN_ERR(print_user_rights(NULL, NULL, 0, &authz->anon_rights, pool)); if (authz->has_authn_rights) - print_user_rights(NULL, NULL, 0, &authz->authn_rights, pool); + SVN_ERR(print_user_rights(NULL, NULL, 0, &authz->authn_rights, pool)); SVN_ERR(svn_iter_apr_hash(NULL, authz->user_rights, print_user_rights, NULL, pool)); printf("\n\n"); Modified: subversion/branches/better-pristines/subversion/tests/libsvn_repos/dump-load-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_repos/dump-load-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_repos/dump-load-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_repos/dump-load-test.c Tue Jan 2 19:52:28 2018 @@ -81,7 +81,7 @@ test_dump_bad_props(svn_stringbuf_t **du notify_func, notify_baton, NULL, NULL, NULL, NULL, pool)); - svn_stream_close(stream); + SVN_ERR(svn_stream_close(stream)); /* Check that the property appears in the dump data */ expected_str = apr_psprintf(pool, "K %d\n%s\n" @@ -131,7 +131,7 @@ test_load_bad_props(svn_stringbuf_t *dum notify_func, notify_baton, NULL, NULL, /*cancellation*/ pool)); - svn_stream_close(stream); + SVN_ERR(svn_stream_close(stream)); /* Check the loaded property */ fs = svn_repos_fs(repos); Modified: subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.c Tue Jan 2 19:52:28 2018 @@ -70,12 +70,12 @@ get_config_file_path(const char **cfg_fi } static const char *config_keys[] = { "foo", "a", "b", "c", "d", "e", "f", "g", - "h", "i", NULL }; + "h", "i", "m", NULL }; static const char *config_values[] = { "bar", "Aa", "100", "bar", "a %(bogus)s oyster bar", "%(bogus)s shmoo %(", "%Aa", "lyrical bard", "%(unterminated", - "Aa 100", NULL }; + "Aa 100", "foo bar baz", NULL }; static svn_error_t * test_text_retrieval(const svn_test_opts_t *opts, Modified: subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.cfg URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.cfg?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.cfg (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_subr/config-test.cfg Tue Jan 2 19:52:28 2018 @@ -45,6 +45,10 @@ j=some %(k)scle k=c%(j)sy # Depends on a cyclic definition l=depends on a %(j)scycle! +# line continuation +m = foo + bar + baz [UpperCaseSection] a=Aa Modified: subversion/branches/better-pristines/subversion/tests/libsvn_subr/mergeinfo-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_subr/mergeinfo-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_subr/mergeinfo-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_subr/mergeinfo-test.c Tue Jan 2 19:52:28 2018 @@ -1762,7 +1762,7 @@ test_rangelist_merge_overlap(apr_pool_t svn_string_t * tmp_string; svn_rangelist_t *range_list; - svn_rangelist_to_string(&tmp_string, rangelist, pool); + SVN_ERR(svn_rangelist_to_string(&tmp_string, rangelist, pool)); SVN_ERR(svn_rangelist__parse(&range_list, tmp_string->data, pool)); } Modified: subversion/branches/better-pristines/subversion/tests/libsvn_subr/priority-queue-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_subr/priority-queue-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_subr/priority-queue-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_subr/priority-queue-test.c Tue Jan 2 19:52:28 2018 @@ -125,7 +125,7 @@ verify_queue_order(svn_priority_queue__t } /* the queue should now be empty */ - verify_empty_queue(queue); + SVN_ERR(verify_empty_queue(queue)); return SVN_NO_ERROR; } @@ -154,7 +154,7 @@ test_empty_queue(apr_pool_t *pool) svn_priority_queue__t *queue = svn_priority_queue__create(elements, compare_func); - verify_empty_queue(queue); + SVN_ERR(verify_empty_queue(queue)); return SVN_NO_ERROR; } @@ -214,7 +214,7 @@ test_update(apr_pool_t *pool) } /* the queue should now be empty */ - verify_empty_queue(queue); + SVN_ERR(verify_empty_queue(queue)); return SVN_NO_ERROR; } Modified: subversion/branches/better-pristines/subversion/tests/libsvn_subr/subst_translate-test.c URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/subversion/tests/libsvn_subr/subst_translate-test.c?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/subversion/tests/libsvn_subr/subst_translate-test.c (original) +++ subversion/branches/better-pristines/subversion/tests/libsvn_subr/subst_translate-test.c Tue Jan 2 19:52:28 2018 @@ -158,7 +158,7 @@ test_svn_subst_translate_string2_null_en }; const char **other_locale; - strncpy(orig_lc_all, setlocale(LC_ALL, NULL), sizeof (orig_lc_all)); + strncpy(orig_lc_all, setlocale(LC_ALL, NULL), sizeof (orig_lc_all) - 1); for (other_locale = other_locales; *other_locale != NULL; ++other_locale) { Modified: subversion/branches/better-pristines/tools/client-side/bash_completion URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/tools/client-side/bash_completion?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/tools/client-side/bash_completion (original) +++ subversion/branches/better-pristines/tools/client-side/bash_completion Tue Jan 2 19:52:28 2018 @@ -128,7 +128,7 @@ function _svn_complete_target() { COMPREPLY=( $(compgen -d -S '/' -X '*/.*' -- $cur ) ) return elif [[ ( $1 == "all" && $cur == ^/* ) || ( "$colon" == ":" && $cur == //*/* ) ]] - then # we already hava a protocoll and host: autocomplete for svn ls ^/bla | svn ls remote_url | svn checkout remote_url + then # we already have a protocol and host: autocomplete for svn ls ^/bla | svn ls remote_url | svn checkout remote_url local p if [ "$colon" == ":" ] ; then p="$prefix$colon" @@ -248,6 +248,7 @@ _svn() cmds="$cmds patch propdel pdel propedit pedit propget pget proplist" cmds="$cmds plist propset pset relocate resolve resolved revert status" cmds="$cmds switch unlock update upgrade" + cmds="$cmds shelve shelves unshelve" # help options have a strange command status... local helpOpts='--help -h' @@ -445,7 +446,7 @@ _svn() # then we have an argument if [[ $cmd = 'merge' && ! $URL ]] ; then - # fist argument is the source URL for the merge + # first argument is the source URL for the merge URL=$opt fi @@ -881,8 +882,8 @@ _svn() --force" ;; cleanup) - cmdOpts="--diff3-cmd $pOpts --include-externals -q --quiet\ - --remove-ignored --remove-unversioned" + cmdOpts="$pOpts --include-externals -q --quiet\ + --remove-ignored --remove-unversioned --vacuum-pristines" ;; commit|ci) cmdOpts="$mOpts $qOpts $nOpts --targets --editor-cmd $pOpts \ @@ -951,7 +952,7 @@ _svn() cmdOpts="$mOpts $qOpts --editor-cmd $pOpts --parents" ;; move|mv|rename|ren) - cmdOpts="$mOpts $rOpts $qOpts --force --editor-cmd $pOpts \ + cmdOpts="$mOpts $qOpts --force --editor-cmd $pOpts \ --parents --allow-mixed-revisions" ;; patch) @@ -1004,7 +1005,7 @@ _svn() $rOpts $cOpts" ;; switch|sw) - cmdOpts="--relocate $rOpts $nOpts $qOpts $pOpts --diff3-cmd \ + cmdOpts="$rOpts $nOpts $qOpts $pOpts --diff3-cmd \ --force --accept --ignore-externals --set-depth \ --ignore-ancestry" ;; @@ -1020,6 +1021,15 @@ _svn() upgrade) cmdOpts="$qOpts $pOpts" ;; + shelve) + cmdOpts="$qOpts --keep-local --delete --list -m --message -F --file --encoding --force-log --editor-cmd --dry-run --depth --targets $cOpts $pOpts" + ;; + unshelve) + cmdOpts="$qOpts --keep-shelved --list --dry-run $pOpts" + ;; + shelves) + cmdOpts="$pOpts" + ;; *) ;; esac @@ -1130,17 +1140,19 @@ _svnadmin () case ${COMP_WORDS[1]} in create) cmdOpts="--bdb-txn-nosync --bdb-log-keep --config-dir \ - --fs-type --pre-1.4-compatible --pre-1.5-compatible \ - --pre-1.6-compatible --compatible-version" + --fs-type --compatible-version" ;; deltify) - cmdOpts="-r --revision -q --quiet" + cmdOpts="-r --revision -q --quiet -M --memory-cache-size" ;; dump) cmdOpts="-r --revision --incremental -q --quiet --deltas \ -M --memory-cache-size -F --file \ --exclude --include --pattern" ;; + dump-revprops) + cmdOpts="-r --revision -q --quiet -F --file" + ;; freeze) cmdOpts="-F --file" ;; @@ -1148,23 +1160,35 @@ _svnadmin () cmdOpts="$cmds" ;; hotcopy) - cmdOpts="--clean-logs" + cmdOpts="--clean-logs --incremental -q --quiet" ;; load) cmdOpts="--ignore-uuid --force-uuid --parent-dir -q --quiet \ --use-pre-commit-hook --use-post-commit-hook \ --bypass-prop-validation -M --memory-cache-size \ - --no-flush-to-disk --normalize-props -F --file" + --no-flush-to-disk --normalize-props -F --file \ + --ignore-dates -r --revision" + ;; + load-revprops) + cmdOpts="-r --revision -q --quiet -F --file \ + --bypass-prop-validation --normalize-props \ + --force-uuid --no-flush-to-disk" ;; lstxns) cmdOpts="-r --revision" ;; lock|unlock) - cmdOpts="--bypass-hooks" + cmdOpts="--bypass-hooks -q --quiet" + ;; + pack) + cmdOpts="-M --memory-cache-size -q --quiet" ;; recover) cmdOpts="--wait" ;; + rmlocks) + cmdOpts="-q --quiet" + ;; rmtxns) cmdOpts="-q --quiet" ;; @@ -1177,7 +1201,9 @@ _svnadmin () --use-post-revprop-change-hook" ;; verify) - cmdOpts="-r --revision -q --quiet" + cmdOpts="-r --revision -t --transaction -q --quiet \ + --check-normalization --keep-going \ + -M --memory-cache-size --metadata-only" ;; *) ;; Modified: subversion/branches/better-pristines/tools/client-side/bash_completion_test URL: http://svn.apache.org/viewvc/subversion/branches/better-pristines/tools/client-side/bash_completion_test?rev=1819877&r1=1819876&r2=1819877&view=diff ============================================================================== --- subversion/branches/better-pristines/tools/client-side/bash_completion_test (original) +++ subversion/branches/better-pristines/tools/client-side/bash_completion_test Tue Jan 2 19:52:28 2018 @@ -20,9 +20,16 @@ # script produces appropriate lists of completions for various incomplete svn # command lines. -if [ ! -f "$1" ] || [ "$2" ]; then - echo "Usage: bash_completion_test BASH_COMPLETION_PATHNAME" +THIS_DIR=`dirname "$0"` +SCRIPT="$1" +if [ -z "$SCRIPT" ]; then + SCRIPT="$THIS_DIR/bash_completion" +fi + +if [ ! -r "$SCRIPT" ] || [ "$2" ]; then + echo "Usage: bash_completion_test [BASH_COMPLETION_PATHNAME]" echo "Tests the specified \"bash_completion\" script," + echo "defaulting to the one in the same directory as this test," echo "including checking it against the \"svn\" program found in the current PATH." exit 1 fi @@ -32,20 +39,26 @@ shopt -s extglob export LC_ALL=C # Execute the script which is to be tested. -. "$1" +. "$SCRIPT" -# From the given incomplete svn command, print a space-separated list of +# From the given incomplete command, print a space-separated list of # possible completions of the last argument (or of an empty first argument # if no subcommand is given). -# Usage: get_svn_completions [SVN-SUBCOMMAND [SVN-OPTION...]] -get_svn_completions() { - COMP_WORDS=(svn "$@") - if [ $# == 0 ]; then +# +# Usage: get_completions SVN-CMD [SVN-SUBCOMMAND [SVN-OPTION...]] +# where SVN-CMD is "svn", "svnadmin", etc.; such that when a leading +# underscore is added, it must name one of the completion functions in +# "bash_completion". +get_completions() { + SVN_CMD="$1" + COMP_WORDS=("$@") + if [ $# == 1 ]; then COMP_CWORD=1 else - COMP_CWORD=$# + COMP_CWORD=$(($#-1)) fi - _svn + # Call the appropriate completion function (e.g. "_svn") with no arguments. + "_$SVN_CMD" echo -n "${COMPREPLY[*]}" } @@ -62,30 +75,38 @@ fail() { } # Check that EXPECTED-WORD is among the completions of the last word in -# SVN-COMMAND. SVN-COMMAND is a single argument to this function, split -# into multiple arguments when passed to "get_svn_completions()". -# Usage: includes SVN-COMMAND EXPECTED-WORD +# SVN-ARGS. SVN-ARGS is a single argument to this function, split +# into multiple arguments when passed to "get_completions()". +# Usage: includes SVN-CMD SVN-ARGS EXPECTED-WORD includes() { - COMPLETIONS=`get_svn_completions $1` - if [[ "$2" != @(${COMPLETIONS// /|}) ]]; then - fail "completions of \"svn $1\" should include \"$2\"" \ + SVN_CMD="$1" + SVN_ARGS="$2" + EXPECTED_WORD="$3" + COMPLETIONS=`get_completions "$SVN_CMD" $SVN_ARGS` + if [[ "$EXPECTED_WORD" != @(${COMPLETIONS// /|}) ]]; then + fail "completions of \"$SVN_CMD $SVN_ARGS\" should include \"$EXPECTED_WORD\"" \ "(completions: $COMPLETIONS)" fi } excludes() { - COMPLETIONS=`get_svn_completions $1` - if [[ "$2" == @(${COMPLETIONS// /|}) ]]; then - fail "completions of \"svn $1\" should exclude \"$2\"" \ + SVN_CMD="$1" + SVN_ARGS="$2" + EXPECTED_WORD="$3" + COMPLETIONS=`get_completions "$SVN_CMD" $SVN_ARGS` + if [[ "$EXPECTED_WORD" == @(${COMPLETIONS// /|}) ]]; then + fail "completions of \"$SVN_CMD $SVN_ARGS\" should exclude \"$EXPECTED_WORD\"" \ "(completions: $COMPLETIONS)" fi } -# Print the valid subcommands for "svn", one per line, sorted. +# Print the valid subcommands for an "svn"-like program, one per line, sorted. # Exclude any synonym that is just a truncation of its full name. -# Usage: get_svn_subcommands +# Usage: get_svn_subcommands SVN-CMD +# where SVN-CMD is "svn" or another program that outputs similar help. get_svn_subcommands() { - svn help | + SVN_CMD="$1" + "$SVN_CMD" help | # Find the relevant lines. sed -n -e '1,/^Available subcommands:$/d;/^$/q;p' | # Remove brackets and commas @@ -111,18 +132,21 @@ get_svn_subcommands() { } # Print the valid option switches for "svn SUBCMD", one per line, sorted. -# Usage: get_svn_options SUBCMD +# Usage: get_svn_options SVN-CMD SUBCMD +# where SVN-CMD is "svn" or another program that outputs similar help. get_svn_options() { - { svn help "$1" | + SVN_CMD="$1" + SUBCMD="$2" + { "$SVN_CMD" help "$SUBCMD" | # Remove deprecated options grep -v deprecated | # Find the relevant lines; remove "arg" and description. - sed -n -e '1,/^Valid options:$/d;/^ -/!d' \ + sed -n -e '1,/^\(Valid\|Global\) options:$/d;/^ -/!d' \ -e 's/\( ARG\)* * : .*//;p' | # Remove brackets; put each word on its own line. tr -d '] ' | tr '[' '\n' # The following options are always accepted but not listed in the help - if [ "$1" != "help" ] ; then + if [ "$SUBCMD" != "help" ] ; then echo "-h" echo "--help" fi @@ -136,36 +160,38 @@ set +e # Do not exit on error TESTS_FAILED= echo "Checking general completion" -includes "he" "help" -includes "" "help" -includes "" "--version" - -echo "Checking list of subcommands" -HELP_SUBCMDS=`get_svn_subcommands | tr "\n" " "` -COMPLETION_SUBCMDS=`get_svn_completions | tr " " "\n" | grep -v "^-" | sort | tr "\n" " "` -if [ "$HELP_SUBCMDS" != "$COMPLETION_SUBCMDS" ]; then - fail "non-option completions for \"svn \" != subcommands accepted" \ - " (non-o. cmpl.: $COMPLETION_SUBCMDS)" \ - " (svn accepts: $HELP_SUBCMDS)" -fi - -echo "Checking list of options for each subcommand" -for SUBCMD in $HELP_SUBCMDS; do - HELP_OPTIONS=`get_svn_options $SUBCMD | tr "\n" " "` - COMPLETION_OPTIONS=`get_svn_completions $SUBCMD - | tr " " "\n" | sort | tr "\n" " "` - if [ "$HELP_OPTIONS" != "$COMPLETION_OPTIONS" ]; then - fail "completions for \"svn $SUBCMD -\" != options accepted" \ - " (completions: $COMPLETION_OPTIONS)" \ - " (svn accepts: $HELP_OPTIONS)" +includes svn "he" "help" +includes svn "" "help" +includes svn "" "--version" + +for SVN_CMD in svn svnadmin svndumpfilter svnlook svnrdump svnsync; do + echo "Checking list of subcommands: $SVN_CMD" + HELP_SUBCMDS=`get_svn_subcommands "$SVN_CMD" | tr "\n" " "` + COMPLETION_SUBCMDS=`get_completions "$SVN_CMD" | tr " " "\n" | grep -v "^-" | sort | tr "\n" " "` + if [ "$HELP_SUBCMDS" != "$COMPLETION_SUBCMDS" ]; then + fail "non-option completions for \"$SVN_CMD\" != subcommands accepted" \ + " (non-o. cmpl.: $COMPLETION_SUBCMDS)" \ + " (help says: $HELP_SUBCMDS)" fi + + echo "Checking list of options for each subcommand" + for SUBCMD in $HELP_SUBCMDS; do + HELP_OPTIONS=`get_svn_options $SVN_CMD $SUBCMD | tr "\n" " "` + COMPLETION_OPTIONS=`get_completions $SVN_CMD $SUBCMD - | tr " " "\n" | sort | tr "\n" " "` + if [ "$HELP_OPTIONS" != "$COMPLETION_OPTIONS" ]; then + fail "completions for \"$SVN_CMD $SUBCMD -\" != options accepted" \ + " (completions: $COMPLETION_OPTIONS)" \ + " (help says: $HELP_OPTIONS)" + fi + done done echo "Checking rejection of synonyms" -excludes "diff -x -u -" "-x" -excludes "diff -x -u --e" "--extensions" -excludes "diff --extensions -u -" "--extensions" -excludes "diff --extensions -u -" "-x" -excludes "diff --extensions=-u -" "-x" +excludes svn "diff -x -u -" "-x" +excludes svn "diff -x -u --e" "--extensions" +excludes svn "diff --extensions -u -" "--extensions" +excludes svn "diff --extensions -u -" "-x" +excludes svn "diff --extensions=-u -" "-x" if [ $TESTS_FAILED ]; then echo "FAILURE: at least one bash_completion test failed."
