Modified: subversion/branches/swig-py3/subversion/svnserve/serve.c URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnserve/serve.c?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/svnserve/serve.c (original) +++ subversion/branches/swig-py3/subversion/svnserve/serve.c Fri Sep 20 11:18:26 2019 @@ -271,17 +271,23 @@ canonicalize_access_file(const char **ac { if (svn_path_is_url(*access_file)) { - *access_file = svn_uri_canonicalize(*access_file, pool); + const char *canonical_url; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, *access_file, + pool, pool)); + *access_file = canonical_url; } else if (svn_path_is_repos_relative_url(*access_file)) { const char *repos_root_url; + const char *canonical_url; SVN_ERR(svn_uri_get_file_url_from_dirent(&repos_root_url, repos_root, pool)); SVN_ERR(svn_path_resolve_repos_relative_url(access_file, *access_file, repos_root_url, pool)); - *access_file = svn_uri_canonicalize(*access_file, pool); + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, *access_file, + pool, pool)); + *access_file = canonical_url; } else { @@ -854,7 +860,7 @@ static svn_error_t *set_path(svn_ra_svn_ svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; - const char *path, *lock_token, *depth_word; + const char *path, *lock_token, *depth_word, *canonical_relpath; svn_revnum_t rev; /* Default to infinity, for old clients that don't send depth. */ svn_depth_t depth = svn_depth_infinity; @@ -865,7 +871,9 @@ static svn_error_t *set_path(svn_ra_svn_ &depth_word)); if (depth_word) depth = svn_depth_from_word(depth_word); - path = svn_relpath_canonicalize(path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_relpath, NULL, path, + pool, pool)); + path = canonical_relpath; if (b->from_rev && strcmp(path, "") == 0) *b->from_rev = rev; if (!b->err) @@ -881,10 +889,12 @@ static svn_error_t *delete_path(svn_ra_s svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; - const char *path; + const char *path, *canonical_relpath; SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path)); - path = svn_relpath_canonicalize(path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_relpath, NULL, path, + pool, pool)); + path = canonical_relpath; if (!b->err) b->err = svn_repos_delete_path(b->report_baton, path, pool); return SVN_NO_ERROR; @@ -894,7 +904,8 @@ static svn_error_t *link_path(svn_ra_svn svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; - const char *path, *url, *lock_token, *fs_path, *depth_word; + const char *path, *url, *lock_token, *fs_path, *depth_word, *canonical_url; + const char *canonical_path; svn_revnum_t rev; svn_boolean_t start_empty; /* Default to infinity, for old clients that don't send depth. */ @@ -906,8 +917,12 @@ static svn_error_t *link_path(svn_ra_svn /* ### WHAT?! The link path is an absolute URL?! Didn't see that coming... -- cmpilato */ - path = svn_relpath_canonicalize(path, pool); - url = svn_uri_canonicalize(url, pool); + + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); + path = canonical_path; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, url, pool, pool)); + url = canonical_url; if (depth_word) depth = svn_depth_from_word(depth_word); if (!b->err) @@ -1123,11 +1138,12 @@ reparent(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *url; + const char *url, *canonical_url; const char *fs_path; SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &url)); - url = svn_uri_canonicalize(url, pool); + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, url, pool, pool)); + url = canonical_url; SVN_ERR(trivial_auth_request(conn, pool, b)); SVN_CMD_ERR(get_fs_path(svn_path_uri_decode(b->repository->repos_url, pool), svn_path_uri_decode(url, pool), @@ -1346,6 +1362,7 @@ add_lock_tokens(const svn_ra_svn__list_t server_baton_t *sb, apr_pool_t *pool) { + const char *canonical_path; int i; svn_fs_access_t *fs_access; @@ -1375,9 +1392,10 @@ add_lock_tokens(const svn_ra_svn__list_t "Lock token isn't a string"); path = path_item->u.string.data; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(sb->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), - pool); + canonical_path, pool); if (! lookup_access(pool, sb, svn_authz_write, full_path, TRUE)) return error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED, NULL, NULL, @@ -1415,6 +1433,7 @@ unlock_paths(const svn_ra_svn__list_t *l int i; apr_pool_t *subpool = svn_pool_create(pool); apr_hash_t *targets = apr_hash_make(subpool); + const char *canonical_path; svn_error_t *err; for (i = 0; i < lock_tokens->nelts; ++i) @@ -1427,9 +1446,10 @@ unlock_paths(const svn_ra_svn__list_t *l token_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 1); path = path_item->u.string.data; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(sb->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - subpool); + canonical_path, subpool); token = token_item->u.string.data; svn_hash_sets(targets, full_path, token); } @@ -1569,7 +1589,7 @@ get_file(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path, *hex_digest; + const char *path, *full_path, *hex_digest, *canonical_path; svn_revnum_t rev; svn_fs_root_t *root; svn_stream_t *contents; @@ -1596,8 +1616,10 @@ get_file(svn_ra_svn_conn_t *conn, if (wants_inherited_props == SVN_RA_SVN_UNSPECIFIED_NUMBER) wants_inherited_props = FALSE; - full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, pool, + pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, canonical_path, + pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -1754,7 +1776,7 @@ get_dir(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t rev; apr_hash_t *entries, *props = NULL; apr_array_header_t *inherited_props; @@ -1780,8 +1802,10 @@ get_dir(svn_ra_svn_conn_t *conn, wants_inherited_props = FALSE; SVN_ERR(parse_dirent_fields(&dirent_fields, dirent_fields_list)); - full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, canonical_path, + pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -1928,7 +1952,7 @@ update(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *target, *full_path, *depth_word; + const char *target, *full_path, *depth_word, *canonical_target; svn_boolean_t recurse; svn_tristate_t send_copyfrom_args; /* Optional; default FALSE */ svn_tristate_t ignore_ancestry; /* Optional; default FALSE */ @@ -1941,7 +1965,9 @@ update(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cb?w3?3", &rev, &target, &recurse, &depth_word, &send_copyfrom_args, &ignore_ancestry)); - target = svn_relpath_canonicalize(target, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; if (depth_word) depth = svn_depth_from_word(depth_word); @@ -1987,7 +2013,7 @@ switch_cmd(svn_ra_svn_conn_t *conn, server_baton_t *b = baton; svn_revnum_t rev; const char *target, *depth_word; - const char *switch_url, *switch_path; + const char *switch_url, *switch_path, *canonical_url, *canonical_target; svn_boolean_t recurse; /* Default to unknown. Old clients won't send depth, but we'll handle that by converting recurse if necessary. */ @@ -1999,9 +2025,12 @@ switch_cmd(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbc?w?33", &rev, &target, &recurse, &switch_url, &depth_word, &send_copyfrom_args, &ignore_ancestry)); - target = svn_relpath_canonicalize(target, pool); - switch_url = svn_uri_canonicalize(switch_url, pool); - + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, switch_url, pool, + pool)); + switch_url = canonical_url; if (depth_word) depth = svn_depth_from_word(depth_word); else @@ -2039,7 +2068,7 @@ status(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *target, *depth_word; + const char *target, *depth_word, *canonical_target; svn_boolean_t recurse; /* Default to unknown. Old clients won't send depth, but we'll handle that by converting recurse if necessary. */ @@ -2048,7 +2077,9 @@ status(svn_ra_svn_conn_t *conn, /* Parse the arguments. */ SVN_ERR(svn_ra_svn__parse_tuple(params, "cb?(?r)?w", &target, &recurse, &rev, &depth_word)); - target = svn_relpath_canonicalize(target, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; if (depth_word) depth = svn_depth_from_word(depth_word); @@ -2078,7 +2109,8 @@ diff(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *target, *versus_url, *versus_path, *depth_word; + const char *target, *versus_url, *versus_path, *depth_word, *canonical_url; + const char *canonical_target; svn_boolean_t recurse, ignore_ancestry; svn_boolean_t text_deltas; /* Default to unknown. Old clients won't send depth, but we'll @@ -2101,8 +2133,12 @@ diff(svn_ra_svn_conn_t *conn, &ignore_ancestry, &versus_url, &text_deltas, &depth_word)); } - target = svn_relpath_canonicalize(target, pool); - versus_url = svn_uri_canonicalize(versus_url, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_target, NULL, target, + pool, pool)); + target = canonical_target; + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, versus_url, + pool, pool)); + versus_url = canonical_url; if (depth_word) depth = svn_depth_from_word(depth_word); @@ -2227,13 +2263,15 @@ get_mergeinfo(svn_ra_svn_conn_t *conn, for (i = 0; i < paths->nelts; i++) { svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(paths, i); - const char *full_path; + const char *full_path, *canonical_path; if (item->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Path is not a string")); - full_path = svn_relpath_canonicalize(item->u.string.data, pool); - full_path = svn_fspath__join(b->repository->fs_path->data, full_path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, + item->u.string.data, pool, pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, + canonical_path, pool); APR_ARRAY_PUSH(canonical_paths, const char *) = full_path; } @@ -2395,7 +2433,7 @@ log_cmd(svn_ra_svn_conn_t *conn, svn_error_t *err, *write_err; server_baton_t *b = baton; svn_revnum_t start_rev, end_rev; - const char *full_path; + const char *full_path, *canonical_path; svn_boolean_t send_changed_paths, strict_node, include_merged_revisions; apr_array_header_t *full_paths, *revprops; svn_ra_svn__list_t *paths, *revprop_items; @@ -2459,9 +2497,10 @@ log_cmd(svn_ra_svn_conn_t *conn, if (elt->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Log path entry not a string")); - full_path = svn_relpath_canonicalize(elt->u.string.data, pool), - full_path = svn_fspath__join(b->repository->fs_path->data, full_path, - pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, + elt->u.string.data, pool, pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, + canonical_path, pool); APR_ARRAY_PUSH(full_paths, const char *) = full_path; } SVN_ERR(trivial_auth_request(conn, pool, b)); @@ -2504,13 +2543,15 @@ check_path(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_fs_root_t *root; svn_node_kind_t kind; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool));; full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -2537,13 +2578,15 @@ stat_cmd(svn_ra_svn_conn_t *conn, { server_baton_t *b = baton; svn_revnum_t rev; - const char *path, *full_path, *cdate; + const char *path, *full_path, *cdate, *canonical_path; svn_fs_root_t *root; svn_dirent_t *dirent; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); - full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, pool, + pool)); + full_path = svn_fspath__join(b->repository->fs_path->data, canonical_path, + pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, @@ -2592,7 +2635,7 @@ get_locations(svn_ra_svn_conn_t *conn, svn_ra_svn__list_t *loc_revs_proto; svn_ra_svn__item_t *elt; int i; - const char *relative_path; + const char *relative_path, *canonical_path; svn_revnum_t peg_revision; apr_hash_t *fs_locations; const char *abs_path; @@ -2605,7 +2648,9 @@ get_locations(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "crl", &relative_path, &peg_revision, &loc_revs_proto)); - relative_path = svn_relpath_canonicalize(relative_path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, relative_path, + pool, pool)); + relative_path = canonical_path; abs_path = svn_fspath__join(b->repository->fs_path->data, relative_path, pool); @@ -2691,7 +2736,7 @@ get_location_segments(svn_ra_svn_conn_t svn_error_t *err, *write_err; server_baton_t *b = baton; svn_revnum_t peg_revision, start_rev, end_rev; - const char *relative_path; + const char *relative_path, *canonical_path; const char *abs_path; authz_baton_t ab; @@ -2702,7 +2747,9 @@ get_location_segments(svn_ra_svn_conn_t SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)(?r)", &relative_path, &peg_revision, &start_rev, &end_rev)); - relative_path = svn_relpath_canonicalize(relative_path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, relative_path, + pool, pool)); + relative_path = canonical_path; abs_path = svn_fspath__join(b->repository->fs_path->data, relative_path, pool); @@ -2854,6 +2901,7 @@ get_file_revs(svn_ra_svn_conn_t *conn, svn_revnum_t start_rev, end_rev; const char *path; const char *full_path; + const char *canonical_path; apr_uint64_t include_merged_revs_param; svn_boolean_t include_merged_revisions; authz_baton_t ab; @@ -2865,7 +2913,9 @@ get_file_revs(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)?B", &path, &start_rev, &end_rev, &include_merged_revs_param)); - path = svn_relpath_canonicalize(path, pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); + path = canonical_path; SVN_ERR(trivial_auth_request(conn, pool, b)); full_path = svn_fspath__join(b->repository->fs_path->data, path, pool); @@ -2908,14 +2958,17 @@ lock(svn_ra_svn_conn_t *conn, const char *path; const char *comment; const char *full_path; + const char *canonical_path; svn_boolean_t steal_lock; svn_revnum_t current_rev; svn_lock_t *l; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b(?r)", &path, &comment, &steal_lock, ¤t_rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool));; full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, full_path, TRUE)); @@ -3007,7 +3060,7 @@ lock_many(svn_ra_svn_conn_t *conn, /* Parse the lock requests from PATH_REVS into TARGETS. */ for (i = 0; i < path_revs->nelts; ++i) { - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t current_rev; svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i); svn_fs_lock_target_t *target; @@ -3021,9 +3074,10 @@ lock_many(svn_ra_svn_conn_t *conn, SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "c(?r)", &path, ¤t_rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - pool); + canonical_path, pool); target = svn_fs_lock_target_create(NULL, current_rev, pool); /* Any duplicate paths, once canonicalized, get collapsed into a @@ -3070,7 +3124,7 @@ lock_many(svn_ra_svn_conn_t *conn, /* Return results in the same order as the paths were supplied. */ for (i = 0; i < path_revs->nelts; ++i) { - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t current_rev; svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i); struct lock_result_t *result; @@ -3082,9 +3136,10 @@ lock_many(svn_ra_svn_conn_t *conn, if (write_err) break; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - subpool); + canonical_path, subpool); result = svn_hash_gets(lmb.results, full_path); if (!result) @@ -3139,14 +3194,16 @@ unlock(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *token, *full_path; + const char *path, *token, *full_path, *canonical_path; svn_boolean_t break_lock; SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b", &path, &token, &break_lock)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); /* Username required unless break_lock was specified. */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, @@ -3190,7 +3247,7 @@ unlock_many(svn_ra_svn_conn_t *conn, for (i = 0; i < unlock_tokens->nelts; i++) { svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i); - const char *path, *full_path, *token; + const char *path, *full_path, *token, *canonical_path; svn_pool_clear(subpool); @@ -3203,9 +3260,10 @@ unlock_many(svn_ra_svn_conn_t *conn, if (!token) token = ""; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - pool); + canonical_path, pool); /* Any duplicate paths, once canonicalized, get collapsed into a single path that is processed once. The result is then @@ -3250,7 +3308,7 @@ unlock_many(svn_ra_svn_conn_t *conn, /* Return results in the same order as the paths were supplied. */ for (i = 0; i < unlock_tokens->nelts; ++i) { - const char *path, *token, *full_path; + const char *path, *token, *full_path, *canonical_path; svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i); struct lock_result_t *result; @@ -3261,9 +3319,10 @@ unlock_many(svn_ra_svn_conn_t *conn, if (write_err) break; + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + subpool, subpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, subpool), - pool); + canonical_path, pool); result = svn_hash_gets(lmb.results, full_path); if (!result) @@ -3313,12 +3372,15 @@ get_lock(svn_ra_svn_conn_t *conn, server_baton_t *b = baton; const char *path; const char *full_path; + const char *canonical_path; svn_lock_t *l; SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, full_path, FALSE)); @@ -3344,6 +3406,7 @@ get_locks(svn_ra_svn_conn_t *conn, server_baton_t *b = baton; const char *path; const char *full_path; + const char *canonical_path; const char *depth_word; svn_depth_t depth; apr_hash_t *locks; @@ -3367,8 +3430,10 @@ get_locks(svn_ra_svn_conn_t *conn, return log_fail_and_flush(err, b, conn, pool); } + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(trivial_auth_request(conn, pool, b)); @@ -3505,15 +3570,17 @@ get_deleted_rev(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t peg_revision; svn_revnum_t end_revision; svn_revnum_t revision_deleted; SVN_ERR(svn_ra_svn__parse_tuple(params, "crr", &path, &peg_revision, &end_revision)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); SVN_ERR(log_command(b, conn, pool, "get-deleted-rev")); SVN_ERR(trivial_auth_request(conn, pool, b)); SVN_CMD_ERR(svn_repos_deleted_rev(b->repository->fs, full_path, peg_revision, @@ -3542,7 +3609,7 @@ get_inherited_props(svn_ra_svn_conn_t *c void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t rev; svn_fs_root_t *root; apr_array_header_t *inherited_props; @@ -3557,9 +3624,10 @@ get_inherited_props(svn_ra_svn_conn_t *c /* Parse arguments. */ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + iterpool, iterpool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, iterpool), - pool); + canonical_path, pool); /* Check authorizations */ SVN_ERR(must_have_access(conn, iterpool, b, svn_authz_read, @@ -3632,7 +3700,7 @@ list(svn_ra_svn_conn_t *conn, void *baton) { server_baton_t *b = baton; - const char *path, *full_path; + const char *path, *full_path, *canonical_path; svn_revnum_t rev; svn_depth_t depth; apr_array_header_t *patterns = NULL; @@ -3658,8 +3726,10 @@ list(svn_ra_svn_conn_t *conn, SVN_ERR(parse_dirent_fields(&rb.dirent_fields, dirent_fields_list)); depth = svn_depth_from_word(depth_word); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + pool, pool)); full_path = svn_fspath__join(b->repository->fs_path->data, - svn_relpath_canonicalize(path, pool), pool); + canonical_path, pool); /* Read the patterns list. */ if (patterns_list) @@ -3822,7 +3892,8 @@ find_repos(const char *url, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - const char *path, *full_path, *fs_path, *hooks_env; + const char *path, *full_path, *fs_path, *hooks_env, *canonical_path; + const char *canonical_root; svn_stringbuf_t *url_buf; svn_boolean_t sasl_requested; @@ -3838,8 +3909,9 @@ find_repos(const char *url, if (path == NULL) path = ""; } - path = svn_relpath_canonicalize(path, scratch_pool); - path = svn_path_uri_decode(path, scratch_pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonical_path, NULL, path, + scratch_pool, scratch_pool)); + path = svn_path_uri_decode(canonical_path, scratch_pool); /* Ensure that it isn't possible to escape the root by disallowing '..' segments. */ @@ -3848,8 +3920,9 @@ find_repos(const char *url, "Couldn't determine repository path"); /* Join the server-configured root with the client path. */ - full_path = svn_dirent_join(svn_dirent_canonicalize(root, scratch_pool), - path, scratch_pool); + SVN_ERR(svn_dirent_canonicalize_safe(&canonical_root, NULL, root, + scratch_pool, scratch_pool)); + full_path = svn_dirent_join(canonical_root, path, scratch_pool); /* Search for a repository in the full path. */ repository->repos_root = svn_repos_find_root_path(full_path, result_pool); @@ -3870,7 +3943,7 @@ find_repos(const char *url, svn_path_remove_components(url_buf, svn_path_component_count(repository->fs_path->data)); repository->repos_url = url_buf->data; - repository->authz_repos_name = svn_dirent_is_child(root, + repository->authz_repos_name = svn_dirent_is_child(canonical_root, repository->repos_root, result_pool); if (repository->authz_repos_name == NULL) @@ -4140,7 +4213,7 @@ construct_server_baton(server_baton_t ** { svn_error_t *err; apr_uint64_t ver; - const char *client_url, *ra_client_string, *client_string; + const char *client_url, *ra_client_string, *client_string, *canonical_url; svn_ra_svn__list_t *caplist; apr_pool_t *conn_pool = svn_ra_svn__get_pool(conn); server_baton_t *b = apr_pcalloc(conn_pool, sizeof(*b)); @@ -4207,15 +4280,21 @@ construct_server_baton(server_baton_t ** &ra_client_string, &client_string)); if (ver != 2) - return SVN_NO_ERROR; - - client_url = svn_uri_canonicalize(client_url, conn_pool); + return svn_error_createf(SVN_ERR_RA_SVN_BAD_VERSION, NULL, + "Unsupported ra_svn protocol version" + " %"APR_UINT64_T_FMT + " (supported versions: [2])", ver); + + SVN_ERR(svn_uri_canonicalize_safe(&canonical_url, NULL, client_url, + conn_pool, scratch_pool)); + client_url = canonical_url; SVN_ERR(svn_ra_svn__set_capabilities(conn, caplist)); /* All released versions of Subversion support edit-pipeline, * so we do not accept connections from clients that do not. */ if (! svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_EDIT_PIPELINE)) - return SVN_NO_ERROR; + return svn_error_create(SVN_ERR_RA_SVN_BAD_VERSION, NULL, + "Missing edit-pipeline capability"); /* find_repos needs the capabilities as a list of words (eventually they get handed to the start-commit hook). While we could add a
Modified: subversion/branches/swig-py3/subversion/tests/cmdline/changelist_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/changelist_tests.py?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/cmdline/changelist_tests.py (original) +++ subversion/branches/swig-py3/subversion/tests/cmdline/changelist_tests.py Fri Sep 20 11:18:26 2019 @@ -73,6 +73,33 @@ def changelist_all_files(wc_dir, name_fu else: svntest.main.run_svn(None, "changelist", clname, full_path) +def select_paths(target_path, depth, changelists, name_func): + """Return the subset of paths found on disk at TARGET_PATH, to a depth + of DEPTH, that match CHANGELISTS. + NAME_FUNC, rather than the working copy, determines what + changelist each path is associated with. + Returned paths are relative to the CWD. + + ### Only the paths of files are returned. + """ + dot_svn = svntest.main.get_admin_name() + for dirpath, dirs, files in os.walk(target_path): + # prepare to return paths relative to WC_DIR + if dot_svn in dirs: + dirs.remove(dot_svn) + if not changelists: # When changelists support dirs, add: "or name_func(name) in changelists" + yield os.path.normpath(dirpath) + if depth == 'empty': + dirs[:] = [] # process no subdirs + continue # nor files + for name in files: + if not changelists or name_func(name) in changelists: + yield os.path.normpath(os.path.join(dirpath, name)) + if depth == 'files': + dirs[:] = [] # process no subdirs + if depth == 'immediates': + depth = 'empty' # process subdirs, but no files nor dirs in them + def clname_from_lastchar_cb(full_path): """Callback for changelist_all_files() that returns a changelist name matching the last character in the file's name. For example, @@ -544,6 +571,8 @@ def info_with_changelists(sbox): #---------------------------------------------------------------------- +@XFail() +@Issue(4826) def diff_with_changelists(sbox): "diff --changelist (wc-wc and repos-wc)" @@ -553,31 +582,20 @@ def diff_with_changelists(sbox): # Add a line of text to all the versioned files in the tree. mod_all_files(wc_dir, "New text.\n") + # Also make a property modification on each directory. + svntest.main.run_svn(None, 'propset', 'p', 'v', '-R', wc_dir) + # Add files to changelists based on the last character in their names. changelist_all_files(wc_dir, clname_from_lastchar_cb) # Now, test various combinations of changelist specification and depths. for is_repos_wc in [0, 1]: - for clname in [['a'], ['i'], ['a', 'i']]: - for depth in ['files', 'infinity']: + for clname in [['a'], ['a', 'i'], []]: + for depth in ['empty', 'files', 'immediates', 'infinity', None]: + for subdir in ['.', 'A', 'A/D']: # Figure out what we expect to see in our diff output. - expected_paths = [] - if 'a' in clname: - if depth == 'infinity': - expected_paths.append('A/B/lambda') - expected_paths.append('A/B/E/alpha') - expected_paths.append('A/B/E/beta') - expected_paths.append('A/D/gamma') - expected_paths.append('A/D/H/omega') - if depth == 'files' or depth == 'infinity': - expected_paths.append('iota') - if 'i' in clname: - if depth == 'infinity': - expected_paths.append('A/D/G/pi') - expected_paths.append('A/D/H/chi') - expected_paths.append('A/D/H/psi') - expected_paths = sorted([os.path.join(wc_dir, x.replace('/', os.sep)) for x in expected_paths]) + expected_paths = sorted(select_paths(sbox.ospath(subdir), depth, clname, clname_from_lastchar_cb)) # Build the command line. args = ['diff'] @@ -589,11 +607,11 @@ def diff_with_changelists(sbox): args.append(depth) if is_repos_wc: args.append('--old') - args.append(sbox.repo_url) + args.append(sbox.repo_url + '/' + subdir) args.append('--new') - args.append(sbox.wc_dir) + args.append(os.path.join(wc_dir, subdir)) else: - args.append(wc_dir) + args.append(os.path.join(wc_dir, subdir)) # Run 'svn diff ...' exit_code, output, errput = svntest.main.run_svn(None, *args) @@ -1180,6 +1198,44 @@ def readd_after_revert(sbox): svntest.actions.run_and_verify_svn(None, [], 'add', dummy) +#---------------------------------------------------------------------- + +# A wc-wc diff returned no results if changelists were specified and the +# diff target dir was not the WC root. +@Issue(4822) +def diff_with_changelists_subdir(sbox): + "diff --changelist (wc-wc) in subdir of WC" + + sbox.build() + wc_dir = sbox.wc_dir + + expected_paths = sbox.ospaths(['A/D/gamma']) + subdir = 'A/D' + clname = 'a' + + for path in expected_paths: + svntest.main.file_append(path, "New text.\n") + svntest.main.run_svn(None, "changelist", clname, *expected_paths) + + # Run 'svn diff ...' + exit_code, output, errput = svntest.main.run_svn(None, + 'diff', '--changelist', clname, + sbox.ospath(subdir)) + + # Filter the output for lines that begin with 'Index:', and + # reduce even those lines to just the actual path. + paths = sorted([x[7:].rstrip() for x in output if x[:7] == 'Index: ']) + + # Diff output on Win32 uses '/' path separators. + if sys.platform == 'win32': + paths = [x.replace('/', os.sep) for x in paths] + + # And, compare! + if (paths != expected_paths): + raise svntest.Failure("Expected paths (%s) and actual paths (%s) " + "don't gel" + % (str(expected_paths), str(paths))) + ######################################################################## # Run the tests @@ -1203,6 +1259,7 @@ test_list = [ None, add_remove_non_existent_target, add_remove_unversioned_target, readd_after_revert, + diff_with_changelists_subdir, ] if __name__ == '__main__': Modified: subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout (original) +++ subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout Fri Sep 20 11:18:26 2019 @@ -47,15 +47,8 @@ Available subcommands: unlock update (up) upgrade - x-shelf-diff - x-shelf-drop - x-shelf-list (x-shelves) - x-shelf-list-by-paths - x-shelf-log - x-shelf-save - x-shelve - x-unshelve - x-wc-copy-mods + +(Use '-v' to show experimental subcommands.) Subversion is a tool for version control. For additional information, see http://subversion.apache.org/ Modified: subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original) +++ subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Fri Sep 20 11:18:26 2019 @@ -135,30 +135,7 @@ Valid options: 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) - --force-interactive : do interactive prompting even if standard input - is not a terminal device - --trust-server-cert : deprecated; same as - --trust-server-cert-failures=unknown-ca - --trust-server-cert-failures ARG : with --non-interactive, accept SSL server - certificates with failures; ARG is comma-separated - list of 'unknown-ca' (Unknown Authority), - 'cn-mismatch' (Hostname mismatch), 'expired' - (Expired certificate), 'not-yet-valid' (Not yet - valid certificate) and 'other' (all other not - separately classified certificate errors). - --config-dir ARG : read user configuration files from directory ARG - --config-option ARG : set user configuration option in the format: - FILE:SECTION:OPTION=[VALUE] - For example: - servers:global:http-library=serf +(Use '-v' to show global and experimental options.) switch (sw): Update the working copy to a different URL within the same repository. usage: 1. switch URL[@PEGREV] [PATH] @@ -226,28 +203,5 @@ Valid options: 'p', 'mc', 'tc', 'mf', 'tf', 'e', 'l', 'r') --relocate : deprecated; use 'svn relocate' -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) - --force-interactive : do interactive prompting even if standard input - is not a terminal device - --trust-server-cert : deprecated; same as - --trust-server-cert-failures=unknown-ca - --trust-server-cert-failures ARG : with --non-interactive, accept SSL server - certificates with failures; ARG is comma-separated - list of 'unknown-ca' (Unknown Authority), - 'cn-mismatch' (Hostname mismatch), 'expired' - (Expired certificate), 'not-yet-valid' (Not yet - valid certificate) and 'other' (all other not - separately classified certificate errors). - --config-dir ARG : read user configuration files from directory ARG - --config-option ARG : set user configuration option in the format: - FILE:SECTION:OPTION=[VALUE] - For example: - servers:global:http-library=serf +(Use '-v' to show global and experimental options.) Modified: subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout (original) +++ subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout Fri Sep 20 11:18:26 2019 @@ -47,15 +47,8 @@ Available subcommands: unlock update (up) upgrade - x-shelf-diff - x-shelf-drop - x-shelf-list (x-shelves) - x-shelf-list-by-paths - x-shelf-log - x-shelf-save - x-shelve - x-unshelve - x-wc-copy-mods + +(Use '-v' to show experimental subcommands.) Subversion is a tool for version control. For additional information, see http://subversion.apache.org/ Modified: subversion/branches/swig-py3/subversion/tests/cmdline/mod_dav_svn_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/mod_dav_svn_tests.py?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/cmdline/mod_dav_svn_tests.py (original) +++ subversion/branches/swig-py3/subversion/tests/cmdline/mod_dav_svn_tests.py Fri Sep 20 11:18:26 2019 @@ -640,6 +640,53 @@ def propfind_propname(sbox): actual_response = r.read() verify_xml_response(expected_response, actual_response) +@SkipUnless(svntest.main.is_ra_type_dav) +def last_modified_header(sbox): + "verify 'Last-Modified' header on 'external' GETs" + + sbox.build(create_wc=False, read_only=True) + + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + } + + h = svntest.main.create_http_connection(sbox.repo_url) + + # GET /repos/iota + # Expect to see a Last-Modified header. + h.request('GET', sbox.repo_url + '/iota', None, headers) + r = h.getresponse() + if r.status != httplib.OK: + raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason)) + svntest.verify.compare_and_display_lines(None, 'Last-Modified', + svntest.verify.RegexOutput('.+'), + r.getheader('Last-Modified')) + r.read() + + # HEAD /repos/iota + # Expect to see a Last-Modified header. + h.request('HEAD', sbox.repo_url + '/iota', None, headers) + r = h.getresponse() + if r.status != httplib.OK: + raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason)) + svntest.verify.compare_and_display_lines(None, 'Last-Modified', + svntest.verify.RegexOutput('.+'), + r.getheader('Last-Modified')) + r.read() + + # GET /repos/!svn/rvr/1/iota + # There should not be a Last-Modified header (it's costly and not useful, + # see r1724790) + h.request('GET', sbox.repo_url + '/!svn/rvr/1/iota', None, headers) + r = h.getresponse() + if r.status != httplib.OK: + raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason)) + last_modified = r.getheader('Last-Modified') + if last_modified: + raise svntest.Failure('Unexpected Last-Modified header: %s' % last_modified) + r.read() + + ######################################################################## # Run the tests @@ -652,6 +699,7 @@ test_list = [ None, propfind_404, propfind_allprop, propfind_propname, + last_modified_header, ] serial_only = True Modified: subversion/branches/swig-py3/subversion/tests/cmdline/shelf_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/shelf_tests.py?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/cmdline/shelf_tests.py (original) +++ subversion/branches/swig-py3/subversion/tests/cmdline/shelf_tests.py Fri Sep 20 11:18:26 2019 @@ -900,6 +900,8 @@ def run_and_verify_shelf_diff_summarize( svntest.verify.display_trees(None, 'DIFF OUTPUT TREE', output_tree, actual) raise +#---------------------------------------------------------------------- + # Exercise a very basic case of shelf-diff. def shelf_diff_simple(sbox): "shelf diff simple" @@ -945,6 +947,23 @@ def shelf_diff_simple(sbox): }) run_and_verify_shelf_diff_summarize(expected_diff, 'foo') +#---------------------------------------------------------------------- + +@XFail() +@Issue(4827) +def shelve_with_kw_translation(sbox): + "shelve with kw translation" + sbox.build(empty=True) + sbox.simple_add_text('$Rev$\n', 'file') + sbox.simple_propset('svn:keywords', 'rev', 'file') + sbox.simple_commit() + sbox.simple_update() + + def modifier(sbox): + sbox.simple_append('file', 'New line\n') + + shelve_unshelve(sbox, modifier) + ######################################################################## # Run the tests @@ -982,6 +1001,7 @@ test_list = [ None, unshelve_text_prop_merge, unshelve_text_prop_conflict, shelf_diff_simple, + shelve_with_kw_translation, ] if __name__ == '__main__': Modified: subversion/branches/swig-py3/subversion/tests/cmdline/svntest/main.py URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/svntest/main.py?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/cmdline/svntest/main.py (original) +++ subversion/branches/swig-py3/subversion/tests/cmdline/svntest/main.py Fri Sep 20 11:18:26 2019 @@ -57,7 +57,7 @@ from svntest import Failure from svntest import Skip from svntest.wc import StateItem as Item -SVN_VER_MINOR = 13 +SVN_VER_MINOR = 14 ###################################################################### # Propchange: subversion/branches/swig-py3/subversion/tests/libsvn_subr/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Fri Sep 20 11:18:26 2019 @@ -59,3 +59,4 @@ test_apr_trunc_workaround save-cleartext test_stream_readline_file_crlf test_stream_readline_file_lf +test_stream_readline_file_nul Modified: subversion/branches/swig-py3/subversion/tests/libsvn_subr/stream-test.c URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/libsvn_subr/stream-test.c?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/libsvn_subr/stream-test.c (original) +++ subversion/branches/swig-py3/subversion/tests/libsvn_subr/stream-test.c Fri Sep 20 11:18:26 2019 @@ -1000,6 +1000,71 @@ test_stream_readline_file_crlf(apr_pool_ return SVN_NO_ERROR; } +static svn_error_t * +test_stream_readline_file_nul(apr_pool_t *pool) +{ + /* Test is written based on the problem report in + https://lists.apache.org/thread.html/c96eb5618ac0bf6e083345e0fdcdcf834e30913f26eabe6ada7bab62@%3Cusers.subversion.apache.org%3E + where the user had an OOM when calling `svndumpfilter` with + a (most likely) invalid dump containing nul bytes. + */ + const char data[] = + { + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', + 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n', 'a', '\0', '\n' + }; + const char *tmp_dir; + const char *tmp_file; + svn_stream_t *stream; + + SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "test_stream_readline_file_nul", pool)); + SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool)); + SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool)); + svn_test_add_dir_cleanup(tmp_dir); + + tmp_file = svn_dirent_join(tmp_dir, "file", pool); + SVN_ERR(svn_io_file_create_bytes(tmp_file, data, sizeof(data), pool)); + SVN_ERR(svn_stream_open_readonly(&stream, tmp_file, pool, pool)); + + while (1) + { + svn_boolean_t eof; + svn_stringbuf_t *line; + + SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, pool)); + if (eof) + break; + + /* Don't check the contents of the `line` here, at least for now. + + In other words, we just test that this case does not crash or cause + unexpected errors. The reason is that currently our `readline_fn` + implementations have inconsistent behavior when dealing with \0 bytes, + handling those differently, either in strchr() or memchr() styles. + + Once we make them consistent (or even decide to bail out with an error + for \0), this part of the test should start properly checking `data`; + maybe also for non-file streams. + */ + } + + SVN_ERR(svn_stream_close(stream)); + + return SVN_NO_ERROR; +} + /* The test table. */ static int max_threads = 1; @@ -1037,6 +1102,8 @@ static struct svn_test_descriptor_t test "test reading LF-terminated lines from file"), SVN_TEST_PASS2(test_stream_readline_file_crlf, "test reading CRLF-terminated lines from file"), + SVN_TEST_PASS2(test_stream_readline_file_nul, + "test reading line from file with nul bytes"), SVN_TEST_NULL }; Modified: subversion/branches/swig-py3/subversion/tests/libsvn_wc/wc-queries-test.c URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/subversion/tests/libsvn_wc/wc-queries-test.c (original) +++ subversion/branches/swig-py3/subversion/tests/libsvn_wc/wc-queries-test.c Fri Sep 20 11:18:26 2019 @@ -747,7 +747,7 @@ test_query_expectations(apr_pool_t *scra as 'DROP TABLE foo', but the performance of such statements is not our concern here. */ - /* "Slow" statements do expect too see a warning, however. */ + /* "Slow" statements do expect to see a warning, however. */ if (is_slow_statement(i)) warned = TRUE; } Modified: subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnbuild.sh URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnbuild.sh?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnbuild.sh (original) +++ subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnbuild.sh Fri Sep 20 11:18:26 2019 @@ -22,8 +22,10 @@ set -e set -x +(test -h ../GNUmakefile || ln -s ../unix-build/Makefile.svn ../GNUmakefile) +(cd .. && gmake dirs-create fetch) url="$(svn info --show-item url)" branch="${url##*/}" -(test -h ../GNUmakefile || ln -s ../unix-build/Makefile.svn ../GNUmakefile) +mkdir -p ../objdir/svn-${branch} touch ../objdir/svn-${branch}/.retrieved (cd .. && gmake BRANCH="$branch" THREADING="no" JAVA="no" MAKE_JOBS=8) Modified: subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svncheck.sh URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svncheck.sh?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svncheck.sh (original) +++ subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svncheck.sh Fri Sep 20 11:18:26 2019 @@ -26,7 +26,7 @@ url="$(svn info --show-item url)" branch="${url##*/}" export MALLOC_OPTIONS=S (cd .. && gmake BRANCH="$branch" PARALLEL="4" THREADING="no" JAVA="no" \ - EXCLUSIVE_WC_LOCKS=1 \ + EXCLUSIVE_WC_LOCKS=1 SVN_CHECK_FS_BACKENDS=fsfs \ svn-check-local \ svn-check-svn \ svn-check-neon \ Modified: subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnclean.sh URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnclean.sh?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnclean.sh (original) +++ subversion/branches/swig-py3/tools/buildbot/slaves/bb-openbsd/svnclean.sh Fri Sep 20 11:18:26 2019 @@ -22,8 +22,6 @@ set -e set -x -url="$(svn info --show-item url)" -branch="${url##*/}" (test -h ../svn-trunk || ln -s build ../svn-trunk) for i in $(jot - 6 12); do (test -h ../svn-1.${i}.x || ln -s build ../svn-1.${i}.x) @@ -33,6 +31,8 @@ svn update ../../unix-build newlastchangedrev="$(svn info --show-item=last-changed-revision ../../unix-build/Makefile.svn)" (test -h ../GNUmakefile || ln -s ../unix-build/Makefile.svn ../GNUmakefile) # always rebuild svn, but only rebuild dependencies if Makefile.svn has changed +url="$(svn info --show-item url)" +branch="${url##*/}" if [ "$lastchangedrev" != "$newlastchangedrev" ]; then (cd .. && gmake BRANCH="$branch" reset clean) else Modified: subversion/branches/swig-py3/tools/dev/unix-build/Makefile.svn URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/tools/dev/unix-build/Makefile.svn?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/tools/dev/unix-build/Makefile.svn (original) +++ subversion/branches/swig-py3/tools/dev/unix-build/Makefile.svn Fri Sep 20 11:18:26 2019 @@ -46,6 +46,7 @@ USE_HTTPV1 ?= no USE_AUTHZ_SHORT_CIRCUIT ?= no RAMDISK ?= /ramdisk MAKE_JOBS ?= 4 +SVN_CHECK_FS_BACKENDS ?= fsfs bdb PWD = $(shell pwd) UNAME = $(shell uname) @@ -191,12 +192,12 @@ NEON_URL = http://ftp.openbsd.org/pub/Op SERF_URL = https://svn.apache.org/repos/asf/serf/tags/$(SERF_VER) SERF_OLD_URL = https://svn.apache.org/repos/asf/serf/tags/$(SERF_OLD_VER) SQLITE_URL = https://www.sqlite.org/2017/$(SQLITE_DIST) -CYRUS_SASL_URL = ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/$(CYRUS_SASL_DIST) +CYRUS_SASL_URL = https://github.com/cyrusimap/cyrus-sasl/releases/download/cyrus-sasl-${CYRUS_SASL_VER}/$(CYRUS_SASL_DIST) LIBMAGIC_URL = ftp://ftp.astron.com/pub/file/$(LIBMAGIC_DIST) RUBY_URL = https://cache.ruby-lang.org/pub/ruby/2.4/$(RUBY_DIST) -BZ2_URL = https://ftp.openbsd.org/pub/OpenBSD/distfiles/$(BZ2_DIST) +BZ2_URL = https://stsp.name/distfiles/$(BZ2_DIST) PYTHON_URL = https://python.org/ftp/python/$(PYTHON_VER)/$(PYTHON_DIST) -JUNIT_URL = https://downloads.sourceforge.net/project/junit/junit/$(JUNIT_VER)/$(JUNIT_DIST) +JUNIT_URL = https://stsp.name/distfiles/$(JUNIT_DIST) GETTEXT_URL = https://ftp.gnu.org/pub/gnu/gettext/$(GETTEXT_DIST) LZ4_URL = https://github.com/lz4/lz4/archive/v$(LZ4_VER).tar.gz @@ -2135,7 +2136,7 @@ stop-svnserve: $(SVNSERVE_STOP_CMD) define do_check --cd $(svn_builddir) && for fs in fsfs bdb; do \ +-cd $(svn_builddir) && for fs in $(SVN_CHECK_FS_BACKENDS); do \ echo "Begin test: $(subst svn-check-,,$@) x $$fs"; \ test -d "$(RAMDISK)/tmp" && export TMPDIR="$(RAMDISK)/tmp"; \ env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(LIB_PTHREAD_HACK) \ Modified: subversion/branches/swig-py3/tools/dist/release.py URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/tools/dist/release.py?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/tools/dist/release.py (original) +++ subversion/branches/swig-py3/tools/dist/release.py Fri Sep 20 11:18:26 2019 @@ -77,6 +77,14 @@ tool_versions = { 'swig' : ['3.0.12', '7cf9f447ae7ed1c51722efc45e7f14418d15d7a1e143ac9f09a668999f4fc94d'], }, + '1.13' : { + 'autoconf' : ['2.69', + '954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969'], + 'libtool' : ['2.4.6', + 'e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3'], + 'swig' : ['3.0.12', + '7cf9f447ae7ed1c51722efc45e7f14418d15d7a1e143ac9f09a668999f4fc94d'], + }, '1.12' : { 'autoconf' : ['2.69', '954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969'], @@ -126,11 +134,11 @@ recommended_release = '1.12' supported_release_lines = frozenset({"1.9", "1.10", "1.12", "1.13"}) # Some constants -repos = 'https://svn.apache.org/repos/asf/subversion' -secure_repos = 'https://svn.apache.org/repos/asf/subversion' +svn_repos = 'https://svn.apache.org/repos/asf/subversion' dist_repos = 'https://dist.apache.org/repos/dist' dist_dev_url = dist_repos + '/dev/subversion' dist_release_url = dist_repos + '/release/subversion' +dist_archive_url = 'https://archive.apache.org/dist/subversion' KEYS = 'https://people.apache.org/keys/group/subversion.asc' extns = ['zip', 'tar.gz', 'tar.bz2'] @@ -284,6 +292,15 @@ def get_target(args): else: return get_deploydir(args.base_dir) +def get_branch_path(args): + if not args.branch: + try: + args.branch = 'branches/%d.%d.x' % (args.version.major, args.version.minor) + except AttributeError: + raise RuntimeError("Please specify the release version label or --branch-path") + + return args.branch.rstrip('/') # canonicalize for later comparisons + def get_tmpldir(): return os.path.join(os.path.abspath(sys.path[0]), 'templates') @@ -292,12 +309,14 @@ def get_tmplfile(filename): return open(os.path.join(get_tmpldir(), filename)) except IOError: # Hmm, we had a problem with the local version, let's try the repo - return urllib2.urlopen(repos + '/trunk/tools/dist/templates/' + filename) + return urllib2.urlopen(svn_repos + '/trunk/tools/dist/templates/' + filename) def get_nullfile(): return open(os.path.devnull, 'w') -def run_script(verbose, script, hide_stderr=False): +def run_command(cmd, verbose=True, hide_stderr=False): + if verbose: + print("+ " + ' '.join(cmd)) stderr = None if verbose: stdout = None @@ -306,8 +325,11 @@ def run_script(verbose, script, hide_std if hide_stderr: stderr = get_nullfile() + subprocess.check_call(cmd, stdout=stdout, stderr=stderr) + +def run_script(verbose, script, hide_stderr=False): for l in script.split('\n'): - subprocess.check_call(l.split(), stdout=stdout, stderr=stderr) + run_command(l.split(), verbose, hide_stderr) def download_file(url, target, checksum): response = urllib2.urlopen(url) @@ -323,6 +345,16 @@ def download_file(url, target, checksum) "downloaded: '%s'; expected: '%s'" % \ (target, checksum, checksum2)) +def run_svn(cmd, verbose=True, username=None): + if (username): + cmd[:0] = ['--username', username] + run_command(['svn'] + cmd, verbose) + +def run_svnmucc(cmd, verbose=True, username=None): + if (username): + cmd[:0] = ['--username', username] + run_command(['svnmucc'] + cmd, verbose) + #---------------------------------------------------------------------- # ezt helpers @@ -552,16 +584,12 @@ def replace_lines(path, actions): def roll_tarballs(args): 'Create the release artifacts.' - if not args.branch: - args.branch = 'branches/%d.%d.x' % (args.version.major, args.version.minor) - - branch = args.branch # shorthand - branch = branch.rstrip('/') # canonicalize for later comparisons + branch = get_branch_path(args) logging.info('Rolling release %s from branch %s@%d' % (args.version, branch, args.revnum)) - check_copyright_year(repos, args.branch, args.revnum) + check_copyright_year(svn_repos, branch, args.revnum) # Ensure we've got the appropriate rolling dependencies available autoconf = AutoconfDep(args.base_dir, False, args.verbose, @@ -580,7 +608,7 @@ def roll_tarballs(args): if branch != 'trunk': # Make sure CHANGES is sync'd. - compare_changes(repos, branch, args.revnum) + compare_changes(svn_repos, branch, args.revnum) # Ensure the output directory doesn't already exist if os.path.exists(get_deploydir(args.base_dir)): @@ -591,9 +619,10 @@ def roll_tarballs(args): logging.info('Preparing working copy source') shutil.rmtree(get_workdir(args.base_dir), True) - run_script(args.verbose, 'svn checkout %s %s' - % (repos + '/' + branch + '@' + str(args.revnum), - get_workdir(args.base_dir))) + run_svn(['checkout', + svn_repos + '/' + branch + '@' + str(args.revnum), + get_workdir(args.base_dir)], + verbose=args.verbose) # Exclude stuff we don't want in the tarball, it will not be present # in the exported tree. @@ -604,8 +633,8 @@ def roll_tarballs(args): exclude += ['packages', 'www'] cwd = os.getcwd() os.chdir(get_workdir(args.base_dir)) - run_script(args.verbose, - 'svn update --set-depth exclude %s' % " ".join(exclude)) + run_svn(['update', '--set-depth=exclude'] + exclude, + verbose=args.verbose) os.chdir(cwd) if args.patches: @@ -615,10 +644,10 @@ def roll_tarballs(args): for name in os.listdir(args.patches): if name.find(majmin) != -1 and name.endswith('patch'): logging.info('Applying patch %s' % name) - run_script(args.verbose, - '''svn patch %s %s''' - % (os.path.join(args.patches, name), - get_workdir(args.base_dir))) + run_svn(['patch', + os.path.join(args.patches, name), + get_workdir(args.base_dir)], + verbose=args.verbose) # Massage the new version number into svn_version.h. ver_tag, ver_numtag = args.version.get_ver_tags(args.revnum) @@ -656,8 +685,9 @@ def roll_tarballs(args): eol_style = "--native-eol CRLF" else: eol_style = "--native-eol LF" - run_script(args.verbose, "svn export %s %s %s" - % (eol_style, get_workdir(args.base_dir), exportdir)) + run_svn(['export', + eol_style, get_workdir(args.base_dir), exportdir], + verbose=args.verbose) def transform_sql(): for root, dirs, files in os.walk(exportdir): @@ -775,7 +805,7 @@ def sign_candidates(args): for e in extns: filename = os.path.join(target, 'subversion-%s.%s' % (args.version, e)) sign_file(filename) - if args.version.major >= 1 and args.version.minor <= 6: + if args.version.major == 1 and args.version.minor <= 6: filename = os.path.join(target, 'subversion-deps-%s.%s' % (args.version, e)) sign_file(filename) @@ -791,14 +821,12 @@ def post_candidates(args): logging.info('Importing tarballs to %s' % dist_dev_url) ver = str(args.version) - svn_cmd = ['svn', 'import', '-m', + svn_cmd = ['import', '-m', 'Add Subversion %s candidate release artifacts' % ver, '--auto-props', '--config-option', 'config:auto-props:*.asc=svn:eol-style=native;svn:mime-type=text/plain', target, dist_dev_url] - if (args.username): - svn_cmd += ['--username', args.username] - subprocess.check_call(svn_cmd) + run_svn(svn_cmd, verbose=args.verbose, username=args.username) #---------------------------------------------------------------------- # Create tag @@ -811,25 +839,19 @@ def create_tag_only(args): logging.info('Creating tag for %s' % str(args.version)) - if not args.branch: - args.branch = 'branches/%d.%d.x' % (args.version.major, args.version.minor) - - branch = secure_repos + '/' + args.branch.rstrip('/') + branch_url = svn_repos + '/' + get_branch_path(args) - tag = secure_repos + '/tags/' + str(args.version) + tag = svn_repos + '/tags/' + str(args.version) - svnmucc_cmd = ['svnmucc', '-m', - 'Tagging release ' + str(args.version)] - if (args.username): - svnmucc_cmd += ['--username', args.username] - svnmucc_cmd += ['cp', str(args.revnum), branch, tag] + svnmucc_cmd = ['-m', 'Tagging release ' + str(args.version)] + svnmucc_cmd += ['cp', str(args.revnum), branch_url, tag] svnmucc_cmd += ['put', os.path.join(target, 'svn_version.h.dist' + '-' + str(args.version)), tag + '/subversion/include/svn_version.h'] # don't redirect stdout/stderr since svnmucc might ask for a password try: - subprocess.check_call(svnmucc_cmd) + run_svnmucc(svnmucc_cmd, verbose=args.verbose, username=args.username) except subprocess.CalledProcessError: if args.version.is_prerelease(): logging.error("Do you need to pass --branch=trunk?") @@ -840,10 +862,7 @@ def bump_versions_on_branch(args): logging.info('Bumping version numbers on the branch') - if not args.branch: - args.branch = 'branches/%d.%d.x' % (args.version.major, args.version.minor) - - branch = secure_repos + '/' + args.branch.rstrip('/') + branch_url = svn_repos + '/' + get_branch_path(args) def replace_in_place(fd, startofline, flat, spare): """In file object FD, replace FLAT with SPARE in the first line @@ -871,11 +890,11 @@ def bump_versions_on_branch(args): args.version.patch + 1)) HEAD = subprocess.check_output(['svn', 'info', '--show-item=revision', - '--', branch]).strip() + '--', branch_url]).strip() HEAD = int(HEAD) def file_object_for(relpath): fd = tempfile.NamedTemporaryFile() - url = branch + '/' + relpath + url = branch_url + '/' + relpath fd.url = url subprocess.check_call(['svn', 'cat', '%s@%d' % (url, HEAD)], stdout=fd) @@ -891,13 +910,14 @@ def bump_versions_on_branch(args): svn_version_h.seek(0, os.SEEK_SET) STATUS.seek(0, os.SEEK_SET) - subprocess.check_call(['svnmucc', '-r', str(HEAD), - '-m', 'Post-release housekeeping: ' - 'bump the %s branch to %s.' - % (branch.split('/')[-1], str(new_version)), - 'put', svn_version_h.name, svn_version_h.url, - 'put', STATUS.name, STATUS.url, - ]) + run_svnmucc(['-r', str(HEAD), + '-m', 'Post-release housekeeping: ' + 'bump the %s branch to %s.' + % (branch_url.split('/')[-1], str(new_version)), + 'put', svn_version_h.name, svn_version_h.url, + 'put', STATUS.name, STATUS.url, + ], + verbose=args.verbose, username=args.username) del svn_version_h del STATUS @@ -939,11 +959,8 @@ def clean_dist(args): for i in sorted(to_keep): logging.info("Saving release '%s'", i) - svnmucc_cmd = ['svnmucc', '-m', 'Remove old Subversion releases.\n' + - 'They are still available at ' + - 'https://archive.apache.org/dist/subversion/'] - if (args.username): - svnmucc_cmd += ['--username', args.username] + svnmucc_cmd = ['-m', 'Remove old Subversion releases.\n' + + 'They are still available at ' + dist_archive_url] for filename in filenames: if Version(filename) not in to_keep: logging.info("Removing %r", filename) @@ -951,7 +968,7 @@ def clean_dist(args): # don't redirect stdout/stderr since svnmucc might ask for a password if 'rm' in svnmucc_cmd: - subprocess.check_call(svnmucc_cmd) + run_svnmucc(svnmucc_cmd, verbose=args.verbose, username=args.username) else: logging.info("Nothing to remove") @@ -967,10 +984,8 @@ def move_to_dist(args): for entry in stdout.split('\n'): if fnmatch.fnmatch(entry, 'subversion-%s.*' % str(args.version)): filenames.append(entry) - svnmucc_cmd = ['svnmucc', '-m', + svnmucc_cmd = ['-m', 'Publish Subversion-%s.' % str(args.version)] - if (args.username): - svnmucc_cmd += ['--username', args.username] svnmucc_cmd += ['rm', dist_dev_url + '/' + 'svn_version.h.dist' + '-' + str(args.version)] for filename in filenames: @@ -979,7 +994,7 @@ def move_to_dist(args): # don't redirect stdout/stderr since svnmucc might ask for a password logging.info('Moving release artifacts to %s' % dist_release_url) - subprocess.check_call(svnmucc_cmd) + run_svnmucc(svnmucc_cmd, verbose=args.verbose, username=args.username) #---------------------------------------------------------------------- # Write announcements @@ -1026,7 +1041,7 @@ def get_fileinfo(args): target = get_target(args) - files = glob.glob(os.path.join(target, 'subversion*-%s*.asc' % args.version)) + files = glob.glob(os.path.join(target, 'subversion*-%s.*.asc' % args.version)) files.sort() class info(object): @@ -1117,14 +1132,12 @@ def get_siginfo(args, quiet=False): import security._gnupg as gnupg gpg = gnupg.GPG() - target = get_target(args) - good_sigs = {} fingerprints = {} output = [] - glob_pattern = os.path.join(target, 'subversion*-%s*.asc' % args.version) - for filename in glob.glob(glob_pattern): + for fileinfo in get_fileinfo(args): + filename = os.path.join(get_target(args), fileinfo.filename + '.asc') text = open(filename).read() keys = text.split(key_start) @@ -1315,13 +1328,13 @@ def write_changelog(args): # New svn_ra_list() API function [D:api] # [D:bindings] JavaHL: Allow access to constructors of a couple JavaHL classes - branch = secure_repos + '/' + args.branch - previous = secure_repos + '/' + args.previous + branch_url = svn_repos + '/' + get_branch_path(args) + previous = svn_repos + '/' + args.previous include_unlabeled = args.include_unlabeled separator_line = ('-' * 72) + '\n' mergeinfo = subprocess.check_output(['svn', 'mergeinfo', '--show-revs', - 'eligible', '--log', branch, previous]) + 'eligible', '--log', branch_url, previous]) log_messages_dict = { # This is a dictionary mapping revision numbers to their respective # log messages. The expression in the "key:" part of the dict @@ -1462,6 +1475,13 @@ def main(): help='''The directory in which to create needed files and folders. The default is the current working directory.''') + parser.add_argument('--branch', + help='''The branch to base the release on, + as a path relative to ^/subversion/. + Default: 'branches/MAJOR.MINOR.x'.''') + parser.add_argument('--username', + help='Username for committing to ' + svn_repos + + ' or ' + dist_repos + '.') subparsers = parser.add_subparsers(title='subcommands') # Setup the parser for the build-env subcommand @@ -1487,9 +1507,6 @@ def main(): help='''The release label, such as '1.7.0-alpha1'.''') subparser.add_argument('revnum', type=lambda arg: int(arg.lstrip('r')), help='''The revision number to base the release on.''') - subparser.add_argument('--branch', - help='''The branch to base the release on, - relative to ^/subversion/.''') subparser.add_argument('--patches', help='''The path to the directory containing patches.''') @@ -1514,8 +1531,6 @@ def main(): subparser.set_defaults(func=post_candidates) subparser.add_argument('version', type=Version, help='''The release label, such as '1.7.0-alpha1'.''') - subparser.add_argument('--username', - help='''Username for ''' + dist_repos + '''.''') subparser.add_argument('--target', help='''The full path to the directory containing release artifacts.''') @@ -1529,11 +1544,6 @@ def main(): help='''The release label, such as '1.7.0-alpha1'.''') subparser.add_argument('revnum', type=lambda arg: int(arg.lstrip('r')), help='''The revision number to base the release on.''') - subparser.add_argument('--branch', - help='''The branch to base the release on, - relative to ^/subversion/.''') - subparser.add_argument('--username', - help='''Username for ''' + secure_repos + '''.''') subparser.add_argument('--target', help='''The full path to the directory containing release artifacts.''') @@ -1546,11 +1556,6 @@ def main(): help='''The release label, such as '1.7.0-alpha1'.''') subparser.add_argument('revnum', type=lambda arg: int(arg.lstrip('r')), help='''The revision number to base the release on.''') - subparser.add_argument('--branch', - help='''The branch to base the release on, - relative to ^/subversion/.''') - subparser.add_argument('--username', - help='''Username for ''' + secure_repos + '''.''') subparser.add_argument('--target', help='''The full path to the directory containing release artifacts.''') @@ -1561,8 +1566,6 @@ def main(): subparser.set_defaults(func=clean_dist) subparser.add_argument('--dist-dir', help='''The directory to clean.''') - subparser.add_argument('--username', - help='''Username for ''' + dist_repos + '''.''') # The move-to-dist subcommand subparser = subparsers.add_parser('move-to-dist', @@ -1572,8 +1575,6 @@ def main(): subparser.set_defaults(func=move_to_dist) subparser.add_argument('version', type=Version, help='''The release label, such as '1.7.0-alpha1'.''') - subparser.add_argument('--username', - help='''Username for ''' + dist_repos + '''.''') # The write-news subcommand subparser = subparsers.add_parser('write-news', @@ -1641,10 +1642,6 @@ def main(): commit messages, optionally labeled with a category like [U:client], [D:api], [U], ...''') subparser.set_defaults(func=write_changelog) - subparser.add_argument('branch', - help='''The branch (or tag or trunk), relative to - ^/subversion/, of which to generate the - changelog, when compared to "previous".''') subparser.add_argument('previous', help='''The "previous" branch or tag, relative to ^/subversion/, to compare "branch" against.''') Modified: subversion/branches/swig-py3/tools/dist/templates/rc-release-ann.ezt URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/tools/dist/templates/rc-release-ann.ezt?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/tools/dist/templates/rc-release-ann.ezt (original) +++ subversion/branches/swig-py3/tools/dist/templates/rc-release-ann.ezt Fri Sep 20 11:18:26 2019 @@ -1,5 +1,6 @@ From: ...@apache.org To: annou...@subversion.apache.org, us...@subversion.apache.org, d...@subversion.apache.org, annou...@apache.org +Reply-To: us...@subversion.apache.org Subject: [[]ANNOUNCE] Apache Subversion [version] released I'm happy to announce the release of Apache Subversion [version]. Modified: subversion/branches/swig-py3/tools/dist/templates/stable-release-ann.ezt URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/tools/dist/templates/stable-release-ann.ezt?rev=1867214&r1=1867213&r2=1867214&view=diff ============================================================================== --- subversion/branches/swig-py3/tools/dist/templates/stable-release-ann.ezt (original) +++ subversion/branches/swig-py3/tools/dist/templates/stable-release-ann.ezt Fri Sep 20 11:18:26 2019 @@ -1,5 +1,6 @@ From: ...@apache.org To: annou...@subversion.apache.org, us...@subversion.apache.org, d...@subversion.apache.org, annou...@apache.org +Reply-To: us...@subversion.apache.org [if-any security]Cc: secur...@apache.org, oss-secur...@lists.openwall.com, bugt...@securityfocus.com [end][if-any security]Subject: [[]SECURITY][[]ANNOUNCE] Apache Subversion [version] released [else]Subject: [[]ANNOUNCE] Apache Subversion [version] released