You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2022/01/14 14:01:51 UTC
svn commit: r1897034 [29/37] - in /subversion/branches/multi-wc-format: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contrib/hook-scripts/ contrib/s...
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/entries-dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/entries-dump.c?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/entries-dump.c (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/entries-dump.c Fri Jan 14 14:01:45 2022
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include <assert.h>
#include <apr_pools.h>
#include <apr_general.h>
@@ -34,6 +35,7 @@
#include "svn_pools.h"
#include "svn_wc.h"
#include "svn_dirent_uri.h"
+#include "svn_xml.h"
#include "private/svn_wc_private.h"
@@ -41,14 +43,61 @@
#include "../../libsvn_wc/lock.h"
static void
-str_value(const char *name, const char *value)
+print_prefix(void)
+{
+ puts("if b'' == '':\n"
+ " def _to_str(s):\n"
+ " return s\n"
+ "else:\n"
+ " def _to_str(s):\n"
+ " return s.decode('utf-8', 'surrogateescape')\n"
+ "\n"
+ "class Entry(object):\n"
+ " \"\"\"An Entry object represents one node's entry in a pre-1.6"
+ " .svn/entries file.\n\n"
+ "Similar to #svn_wc_entry_t, but not all fields are populated.\n\n"
+ "Entry objects are generated by the 'entries-dump'"
+ " test helper tool.\"\"\"\n\n"
+ " if b'' == '':\n"
+ " def set_strval(self, name, val):\n"
+ " self.__setattr__(name, val)\n"
+ " else:\n"
+ " def set_strval(self, name, val):\n"
+ " global _to_str\n"
+ " self.__setattr__(name, _to_str(val))\n");
+}
+
+static void
+print_as_bytes(const char *val)
+{
+ printf("b'");
+ while(*val)
+ {
+ printf("\\x%02x", (unsigned int)(unsigned char)*val++);
+ }
+ printf("'");
+}
+
+static void
+str_value(const char *name, const char *value, apr_pool_t *pool)
{
if (value == NULL)
printf("e.%s = None\n", name);
else
- printf("e.%s = '%s'\n", name, value);
-}
+ {
+ svn_stringbuf_t *escaped_value = NULL;
+ svn_xml_escape_attr_cstring(&escaped_value, value, pool);
+ /* Print the human-readable value. */
+ assert(NULL == strchr(escaped_value->data, '\n'));
+ printf("# e.%s = '%s'\n", name, escaped_value->data);
+
+ /* Print the machine-readable value. */
+ printf("e.set_strval('%s', ", name);
+ print_as_bytes(value);
+ printf(")\n");
+ }
+}
static void
int_value(const char *name, long int value)
@@ -76,6 +125,7 @@ entries_dump(const char *dir_path, svn_w
svn_error_t *err;
svn_wc_context_t *wc_ctx = NULL;
const char *dir_abspath;
+ apr_pool_t *iterpool = svn_pool_create(pool);
SVN_ERR(svn_dirent_get_absolute(&dir_abspath, dir_path, pool));
@@ -124,44 +174,45 @@ entries_dump(const char *dir_path, svn_w
for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
{
+ svn_stringbuf_t *escaped_key;
const char *key = apr_hash_this_key(hi);
const svn_wc_entry_t *entry = apr_hash_this_val(hi);
+ svn_pool_clear(iterpool);
SVN_ERR_ASSERT(strcmp(key, entry->name) == 0);
-
printf("e = Entry()\n");
- str_value("name", entry->name);
+ str_value("name", entry->name, iterpool);
int_value("revision", entry->revision);
- str_value("url", entry->url);
- str_value("repos", entry->repos);
- str_value("uuid", entry->uuid);
+ str_value("url", entry->url, iterpool);
+ str_value("repos", entry->repos, iterpool);
+ str_value("uuid", entry->uuid, iterpool);
int_value("kind", entry->kind);
int_value("schedule", entry->schedule);
bool_value("copied", entry->copied);
bool_value("deleted", entry->deleted);
bool_value("absent", entry->absent);
bool_value("incomplete", entry->incomplete);
- str_value("copyfrom_url", entry->copyfrom_url);
+ str_value("copyfrom_url", entry->copyfrom_url, iterpool);
int_value("copyfrom_rev", entry->copyfrom_rev);
- str_value("conflict_old", entry->conflict_old);
- str_value("conflict_new", entry->conflict_new);
- str_value("conflict_wrk", entry->conflict_wrk);
- str_value("prejfile", entry->prejfile);
+ str_value("conflict_old", entry->conflict_old, iterpool);
+ str_value("conflict_new", entry->conflict_new, iterpool);
+ str_value("conflict_wrk", entry->conflict_wrk, iterpool);
+ str_value("prejfile", entry->prejfile, iterpool);
/* skip: text_time */
/* skip: prop_time */
/* skip: checksum */
int_value("cmt_rev", entry->cmt_rev);
/* skip: cmt_date */
- str_value("cmt_author", entry->cmt_author);
- str_value("lock_token", entry->lock_token);
- str_value("lock_owner", entry->lock_owner);
- str_value("lock_comment", entry->lock_comment);
+ str_value("cmt_author", entry->cmt_author, iterpool);
+ str_value("lock_token", entry->lock_token, iterpool);
+ str_value("lock_owner", entry->lock_owner, iterpool);
+ str_value("lock_comment", entry->lock_comment, iterpool);
/* skip: lock_creation_date */
/* skip: has_props */
/* skip: has_prop_mods */
/* skip: cachable_props */
/* skip: present_props */
- str_value("changelist", entry->changelist);
+ str_value("changelist", entry->changelist, iterpool);
/* skip: working_size */
/* skip: keep_local */
int_value("depth", entry->depth);
@@ -170,8 +221,17 @@ entries_dump(const char *dir_path, svn_w
/* skip: file_external_peg_rev */
/* skip: file_external_rev */
bool_value("locked", locked && *entry->name == '\0');
- printf("entries['%s'] = e\n", (const char *)key);
+ /* Print the human-readable value. */
+ escaped_key = NULL;
+ svn_xml_escape_attr_cstring(&escaped_key, key, iterpool);
+ assert(NULL == strchr(escaped_key->data, '\n'));
+ printf("# entries['%s'] = e\n", escaped_key->data);
+ /* Print the machine-readable value. */
+ printf("entries[_to_str(");
+ print_as_bytes(key);
+ printf(")] = e\n");
}
+ svn_pool_destroy(iterpool);
if (wc_ctx)
SVN_ERR(svn_wc_context_destroy(wc_ctx));
@@ -282,6 +342,7 @@ tree_dump_dir(const char *local_abspath,
{
struct directory_walk_baton *bt = walk_baton;
const char *path;
+ svn_stringbuf_t *escaped_path;
if (kind != svn_node_dir)
return SVN_NO_ERROR;
@@ -307,7 +368,15 @@ tree_dump_dir(const char *local_abspath,
printf("entries = {}\n");
SVN_ERR(entries_dump(path, bt->adm_access, scratch_pool));
- printf("dirs['%s'] = entries\n", path);
+ /* Print the human-readable value. */
+ escaped_path = NULL;
+ svn_xml_escape_attr_cstring(&escaped_path, path, scratch_pool);
+ assert(NULL == strchr(escaped_path->data, '\n'));
+ printf("# dirs['%s'] = entries\n", escaped_path->data);
+ /* Print the machine-readable value. */
+ printf("dirs[_to_str(");
+ print_as_bytes(path);
+ printf(")] = entries\n");
return SVN_NO_ERROR;
}
@@ -384,15 +453,25 @@ main(int argc, const char *argv[])
cmd = NULL;
if (!cmd || !strcmp(cmd, "--entries"))
- err = entries_dump(path, NULL, pool);
+ {
+ print_prefix();
+ err = entries_dump(path, NULL, pool);
+ }
else if (!strcmp(cmd, "--subdirs"))
- err = directory_dump(path, pool);
+ {
+ err = directory_dump(path, pool);
+ }
else if (!strcmp(cmd, "--tree-dump"))
- err = tree_dump(path, pool);
+ {
+ print_prefix();
+ err = tree_dump(path, pool);
+ }
else
- err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
- "Invalid command '%s'",
- cmd);
+ {
+ err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+ "Invalid command '%s'",
+ cmd);
+ }
if (err)
{
svn_handle_error2(err, stderr, FALSE, "entries-dump: ");
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/export_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/export_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/export_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/export_tests.py Fri Jan 14 14:01:45 2022
@@ -1124,6 +1124,81 @@ def export_revision_with_root_relative_e
expected_disk,
'-r', 2)
+def export_keyword_translation_inconsistent_eol(sbox):
+ "export keyword translation with inconsistent EOLs"
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ # Create a file with keywords and inconsistent EOLs, don't set svn:eol-style.
+ sbox.simple_add_text('$LastChangedRevision$\n\r\n', 'dir/file')
+ sbox.simple_propset('svn:keywords', 'LastChangedRevision', 'dir/file')
+ sbox.simple_commit()
+
+ export_target = sbox.add_wc_path('export')
+
+ expected_disk = svntest.wc.State('', {
+ 'dir' : Item(),
+ 'dir/file' : Item("$LastChangedRevision: 1 $\n\r\n"),
+ })
+
+ expected_output = svntest.wc.State(export_target, {
+ '' : Item(status='A '),
+ 'dir' : Item(status='A '),
+ 'dir/file' : Item(status='A ')
+ })
+
+ # We should be able to export without any unexpected errors.
+ svntest.actions.run_and_verify_export2(sbox.repo_url,
+ export_target,
+ expected_output,
+ expected_disk,
+ keep_eol_style=True)
+
+def export_working_copy_eol_translation(sbox):
+ "export working copy with EOL translation"
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('test\n', 'dir/file')
+ sbox.simple_propset('svn:eol-style', 'CRLF', 'dir/file')
+ sbox.simple_commit()
+
+ export_target = sbox.add_wc_path('export')
+
+ expected_disk = svntest.wc.State('', {
+ 'dir' : Item(),
+ 'dir/file' : Item("test\r\n"),
+ })
+
+ expected_output = svntest.wc.State(export_target, {
+ 'dir' : Item(status='A '),
+ 'dir/file' : Item(status='A ')
+ })
+
+ svntest.actions.run_and_verify_export2(sbox.wc_dir,
+ export_target,
+ expected_output,
+ expected_disk,
+ keep_eol_style=True)
+
+def export_working_copy_inconsistent_eol(sbox):
+ "export working copy with inconsistent EOLs"
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('test\n', 'dir/file')
+ sbox.simple_propset('svn:eol-style', 'CRLF', 'dir/file')
+ sbox.simple_commit()
+
+ # Edit the file so that it would have inconsistent EOLs.
+ sbox.simple_append('dir/file', 'test\n\r\n', truncate=True)
+
+ # Attempt to export the working copy, expect an error.
+ export_target = sbox.add_wc_path('export')
+ svntest.actions.run_and_verify_svn(
+ None,
+ "svn: E135000: Inconsistent line ending style\n",
+ 'export',
+ sbox.wc_dir,
+ export_target)
+
########################################################################
# Run the tests
@@ -1162,6 +1237,9 @@ test_list = [ None,
export_file_external,
export_file_externals2,
export_revision_with_root_relative_external,
+ export_keyword_translation_inconsistent_eol,
+ export_working_copy_eol_translation,
+ export_working_copy_inconsistent_eol,
]
if __name__ == '__main__':
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/externals_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/externals_tests.py Fri Jan 14 14:01:45 2022
@@ -2946,7 +2946,7 @@ def url_to_wc_copy_of_externals(sbox):
external_tau_path = os.path.join(wc_dir, "External-WC-to-URL-Copy",
"external", "tau")
expected_stdout = verify.UnorderedOutput([
- " U " + external_root_path + "\n",
+ "A " + external_root_path + "\n",
"\n",
"Fetching external item into '" + external_ex_path + "':\n",
"A " + external_pi_path + "\n",
@@ -2954,8 +2954,6 @@ def url_to_wc_copy_of_externals(sbox):
"A " + external_tau_path + "\n",
"Checked out external at revision 2.\n",
"\n",
- "Checked out revision 2.\n",
- "A " + external_root_path + "\n"
])
exit_code, stdout, stderr = svntest.actions.run_and_verify_svn2(
expected_stdout, [], 0, 'copy', repo_url + '/A/C',
@@ -3913,7 +3911,7 @@ def copy_pin_externals_whitespace_dir(sb
branches_url = repo_url + '/branches'
trunk_wc = sbox.ospath('trunk')
- # Create a new revision to creat interesting pinning revisions
+ # Create a new revision to create interesting pinning revisions
sbox.simple_propset('A', 'B', 'trunk')
sbox.simple_commit('trunk')
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests.py Fri Jan 14 14:01:45 2022
@@ -38,10 +38,6 @@ import svntest
#----------------------------------------------------------------------
-# This directory contains all the expected output from svn.
-getopt_output_dir = os.path.join(os.path.dirname(sys.argv[0]),
- 'getopt_tests_data')
-
# Naming convention for golden files: take the svn command line as a
# single string and apply the following sed transformations:
# echo svn option1 option2 ... | sed -e 's/ /_/g' -e 's/_--/--/g'
@@ -51,6 +47,10 @@ getopt_output_dir = os.path.join(os.path
def load_expected_output(basename):
"load the expected standard output and standard error"
+ # This directory contains all the expected output from svn.
+ getopt_output_dir = os.path.join(os.path.dirname(sys.argv[0]),
+ 'getopt_tests_data')
+
stdout_filename = os.path.join(getopt_output_dir, basename + '_stdout')
stderr_filename = os.path.join(getopt_output_dir, basename + '_stderr')
@@ -233,7 +233,7 @@ def getopt_config_option(sbox):
expected_stderr = '.*W205000.*did you mean.*'
expected_stdout = svntest.verify.AnyOutput
svntest.actions.run_and_verify_svn2(expected_stdout, expected_stderr, 0,
- 'info',
+ 'info',
'--config-option',
'config:miscellanous:diff-extensions=' +
'-u -p',
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout Fri Jan 14 14:01:45 2022
@@ -47,14 +47,6 @@ 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
Subversion is a tool for version control.
For additional information, see http://subversion.apache.org/
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version--verbose_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version--verbose_stdout?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version--verbose_stdout (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version--verbose_stdout Fri Jan 14 14:01:45 2022
@@ -6,7 +6,7 @@ This software consists of contributions
see the NOTICE file for more information.
Subversion is open source software, see http://subversion.apache.org/
-Supported working copy (WC) versions: from 1.8 to 1.12
+Supported working copy (WC) versions: from 1.8 to 1.15
The following repository access (RA) modules are available:
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn--version_stdout Fri Jan 14 14:01:45 2022
@@ -6,7 +6,7 @@ This software consists of contributions
see the NOTICE file for more information.
Subversion is open source software, see http://subversion.apache.org/
-Supported working copy (WC) versions: from 1.8 to 1.12
+Supported working copy (WC) versions: from 1.8 to 1.15
The following repository access (RA) modules are available:
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Fri Jan 14 14:01:45 2022
@@ -135,32 +135,10 @@ 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.
+switch (sw): Update the working copy to a different URL within the same
+repository.
usage: 1. switch URL[@PEGREV] [PATH]
2. switch --relocate FROM-PREFIX TO-PREFIX [PATH...]
@@ -196,9 +174,6 @@ usage: 1. switch URL[@PEGREV] [PATH]
Examples:
svn switch ^/branches/1.x-release
- svn switch --relocate http:// svn://
- svn switch --relocate http://www.example.com/repo/project \
- svn://svn.example.com/repo/project
Valid options:
-r [--revision] ARG : ARG (some commands also take ARG1:ARG2 range)
@@ -226,28 +201,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/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout Fri Jan 14 14:01:45 2022
@@ -47,14 +47,6 @@ 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
Subversion is a tool for version control.
For additional information, see http://subversion.apache.org/
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/info_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/info_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/info_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/info_tests.py Fri Jan 14 14:01:45 2022
@@ -716,6 +716,72 @@ def info_item_uncommmitted(sbox):
sbox.ospath('newfile'), sbox.ospath('newdir'))
+def info_item_size_wc_recursive(sbox):
+ "recursive '--show-item=repos-size' on local path"
+
+ sbox.build(read_only=True)
+
+ svntest.actions.run_and_verify_svn(
+ [], [],
+ 'info', '--show-item=repos-size', '--recursive',
+ sbox.ospath(''))
+
+
+def info_item_size_repos(sbox):
+ "non-recursive '--show-item=repos-size' on URL"
+
+ sbox.build(read_only=True)
+
+ svntest.actions.run_and_verify_svn(
+ "25\n", [],
+ 'info', '--show-item=repos-size',
+ sbox.repo_url + "/iota")
+
+ # Same, but without the newline.
+ svntest.actions.run_and_verify_svn(
+ "25", [],
+ 'info', '--show-item=repos-size', '--no-newline',
+ sbox.repo_url + "/iota")
+
+ # Same, but with "human-readable" output.
+ svntest.actions.run_and_verify_svn(
+ "25 B", [],
+ 'info', '--show-item=repos-size', '--human-readable',
+ sbox.repo_url + "/iota")
+
+ # No output when the URL is a directory.
+ svntest.actions.run_and_verify_svn(
+ [], [],
+ 'info', '--show-item=repos-size',
+ sbox.repo_url)
+
+
+def info_item_size_repos_recursive(sbox):
+ "recursive '--show-item=repos-size' on dir URL"
+
+ sbox.build(read_only=True)
+
+ expected_output = svntest.verify.UnorderedOutput([
+ "25 " + sbox.repo_url + "/iota\n",
+ "27 " + sbox.repo_url + "/A/B/lambda\n",
+ "25 " + sbox.repo_url + "/A/B/E/beta\n",
+ "26 " + sbox.repo_url + "/A/B/E/alpha\n",
+ "23 " + sbox.repo_url + "/A/mu\n",
+ "26 " + sbox.repo_url + "/A/D/gamma\n",
+ "23 " + sbox.repo_url + "/A/D/G/pi\n",
+ "24 " + sbox.repo_url + "/A/D/G/rho\n",
+ "24 " + sbox.repo_url + "/A/D/G/tau\n",
+ "26 " + sbox.repo_url + "/A/D/H/omega\n",
+ "24 " + sbox.repo_url + "/A/D/H/psi\n",
+ "24 " + sbox.repo_url + "/A/D/H/chi\n",
+ ])
+
+ svntest.actions.run_and_verify_svn(
+ expected_output, [],
+ 'info', '--show-item=repos-size', '--recursive',
+ sbox.repo_url)
+
+
def info_item_failures(sbox):
"failure modes of 'svn info --show-item'"
@@ -746,6 +812,158 @@ def info_item_failures(sbox):
'info', '--show-item=revision', '--no-newline',
sbox.ospath('A'), sbox.ospath('iota'))
+ svntest.actions.run_and_verify_svn(
+ None, (r".*E200007: can't show in-repository size.*"),
+ 'info', '--show-item=repos-size',
+ sbox.ospath('iota'))
+
+
+@Issue(4837)
+def info_file_in_file_replaced_dir(sbox):
+ "info, file in file-replaced dir"
+
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('text\n', 'dir/file')
+ sbox.simple_commit(message='Add file')
+
+ sbox.simple_copy('dir/file', 'file-moved')
+ sbox.simple_rm('dir')
+ sbox.simple_add_text('replaced\n', 'dir')
+ sbox.simple_commit(message='Replace dir with file')
+
+ sbox.simple_update()
+
+ expected = {'Relative URL' : r'\^/dir/file',
+ 'Node Kind' : 'file',
+ 'Revision': '1',
+ 'Last Changed Rev': '1',
+ }
+
+ svntest.actions.run_and_verify_info([expected],
+ sbox.repo_url + '/dir/file@1')
+
+@Issue(4869)
+def info_tree_conflict_source(sbox):
+ "info --xml: verify source-left, source-right"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ B_path = os.path.join(wc_dir, 'A', 'B')
+ lambda_path = os.path.join(B_path, 'lambda')
+ alpha_path = os.path.join(B_path, 'E', 'alpha')
+ F_path = os.path.join(B_path, 'F')
+
+ B2_url = sbox.repo_url + '/A/B2'
+ B2_path = os.path.join(wc_dir, 'A', 'B2')
+ lambda2_path = os.path.join(B2_path, 'lambda')
+
+ # Rev 2 copy B to B2
+ sbox.simple_repo_copy('A/B', 'A/B2')
+ sbox.simple_update()
+
+ # Rev 3:
+ # edit A/B/lambda to test text conflict case
+ # add property to A/B/E/alpha to test property conflict case
+ # rename A/B/F to A/B/Z to test tree conflict case
+
+ svntest.main.file_write(lambda_path, 'B/lambda side of conflict')
+ sbox.simple_propset('blue', 'azul', 'A/B/E/alpha')
+ sbox.simple_move('A/B/F', 'A/B/Z');
+ sbox.simple_commit()
+
+ # Rev 4:
+ # edit A/B2/lambda
+ # add property to A/B2/E/alpha
+ # rename A/B2/F to A/B2/Y
+
+ svntest.main.file_write(lambda2_path, 'B2/lambda side of conflict')
+ sbox.simple_propset('blue', 'bleue', 'A/B2/E/alpha')
+ sbox.simple_move('A/B2/F', 'A/B2/Y');
+ sbox.simple_commit()
+
+ # Now merge B2 into B to cause a text conflict, property conflict, and
+ # tree conflict
+ sbox.simple_update()
+
+ svntest.actions.run_and_verify_svn2(svntest.verify.AnyOutput, [],
+ 0, 'merge', B2_url, B_path)
+
+ # Verify 'svn info --xml' on the text conflicted case
+
+ exit_code, output, error = svntest.actions.run_and_verify_svn(None,
+ [], 'info',
+ lambda_path,
+ '--xml')
+
+ verify_xml_elements(output,
+ [('version', {'revision' : '1',
+ 'side' : 'source-left',
+ 'kind' : 'file',
+ 'path-in-repos': 'A/B/lambda',
+ 'repos-url' : sbox.repo_url,
+ },
+ )])
+
+ verify_xml_elements(output,
+ [('version', {'revision' : '4',
+ 'side' : 'source-right',
+ 'kind' : 'file',
+ 'path-in-repos': 'A/B2/lambda',
+ 'repos-url' : sbox.repo_url,
+ },
+ )])
+
+ # Verify 'svn info --xml' on the property conflicted case
+
+ exit_code, output, error = svntest.actions.run_and_verify_svn(None,
+ [], 'info',
+ alpha_path,
+ '--xml')
+
+ verify_xml_elements(output,
+ [('version', {'revision' : '1',
+ 'side' : 'source-left',
+ 'kind' : 'file',
+ 'path-in-repos': 'A/B/E/alpha',
+ 'repos-url' : sbox.repo_url,
+ },
+ )])
+
+ verify_xml_elements(output,
+ [('version', {'revision' : '4',
+ 'side' : 'source-right',
+ 'kind' : 'file',
+ 'path-in-repos': 'A/B2/E/alpha',
+ 'repos-url' : sbox.repo_url,
+ },
+ )])
+
+ # Verify 'svn info --xml' on the tree conflicted case
+
+ exit_code, output, error = svntest.actions.run_and_verify_svn(None,
+ [], 'info',
+ F_path,
+ '--xml')
+
+ verify_xml_elements(output,
+ [('version', {'revision' : '1',
+ 'side' : 'source-left',
+ 'kind' : 'dir',
+ 'path-in-repos': 'A/B/F',
+ 'repos-url' : sbox.repo_url,
+ },
+ )])
+
+ verify_xml_elements(output,
+ [('version', {'revision' : '4',
+ 'side' : 'source-right',
+ 'kind' : 'none',
+ 'path-in-repos': 'A/B2/F',
+ 'repos-url' : sbox.repo_url,
+ },
+ )])
########################################################################
# Run the tests
@@ -767,7 +985,12 @@ test_list = [ None,
info_item_simple_multiple,
info_item_url,
info_item_uncommmitted,
+ info_item_size_wc_recursive,
+ info_item_size_repos,
+ info_item_size_repos_recursive,
info_item_failures,
+ info_file_in_file_replaced_dir,
+ info_tree_conflict_source,
]
if __name__ == '__main__':
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/lock_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/lock_tests.py Fri Jan 14 14:01:45 2022
@@ -1001,7 +1001,7 @@ def lock_and_exebit1(sbox):
if (not gamma_stat & mode_r
or gamma_stat & mode_w
or not gamma_stat & mode_x):
- logger.warn("Commiting a file with 'svn:needs-lock, svn:executable'")
+ logger.warn("Committing a file with 'svn:needs-lock, svn:executable'")
logger.warn("after unlocking modified file's permissions")
raise svntest.Failure
@@ -1065,7 +1065,7 @@ def lock_and_exebit2(sbox):
if (not gamma_stat & mode_r
or gamma_stat & mode_w
or not gamma_stat & mode_x):
- logger.warn("Commiting a file with 'svn:needs-lock, svn:executable'")
+ logger.warn("Committing a file with 'svn:needs-lock, svn:executable'")
logger.warn("did not set the file to read-only, executable")
raise svntest.Failure
@@ -1454,7 +1454,7 @@ def lock_path_not_in_head(sbox):
svntest.actions.run_and_verify_svn(None, [], 'up', '-r1', wc_dir)
expected_lock_fail_err_re = "svn: warning: W160042: " \
"(Path .* doesn't exist in HEAD revision)"
- # Issue #3524 These lock attemtps were triggering an assert over ra_serf:
+ # Issue #3524 These lock attempts were triggering an assert over ra_serf:
#
# working_copies\lock_tests-37>svn lock A\D
# ..\..\..\subversion\libsvn_client\ra.c:275: (apr_err=235000)
@@ -1835,7 +1835,7 @@ def commit_stolen_lock(sbox):
# When removing directories, the locks of contained files were not
# correctly removed from the working copy database, thus they later
# magically reappeared when new files or directories with the same
-# pathes were added.
+# paths were added.
@Issue(4364)
def drop_locks_on_parent_deletion(sbox):
"drop locks when the parent is deleted"
@@ -1856,7 +1856,7 @@ def drop_locks_on_parent_deletion(sbox):
[],
expected_status)
- # now re-add entities to the deleted pathes.
+ # now re-add entities to the deleted paths.
sbox.simple_mkdir('A/B')
sbox.simple_add_text('new file replacing old file', 'A/B/lambda')
sbox.simple_add_text('file replacing former dir', 'A/B/F')
@@ -2479,6 +2479,94 @@ def replace_dir_with_lots_of_locked_file
# This problem was introduced on the 1.8.x branch in r1606976.
sbox.simple_commit()
+def update_add_file_needs_lock(sbox):
+ "update adding a file with svn:needs-lock"
+
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('test\n', 'dir/file')
+ sbox.simple_propset('svn:needs-lock', 'yes', 'dir/file')
+ sbox.simple_commit()
+
+ sbox.simple_update(revision=0)
+ sbox.simple_update(revision=1)
+ is_readonly(sbox.ospath('dir/file'))
+
+def update_edit_file_needs_lock(sbox):
+ "update editing a file with svn:needs-lock"
+
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('test\n', 'dir/file')
+ sbox.simple_commit()
+
+ sbox.simple_append('dir/file', 'edited\n', truncate=True)
+ sbox.simple_propset('svn:needs-lock', 'yes', 'dir/file')
+ sbox.simple_commit()
+
+ sbox.simple_update(revision=1)
+ is_writable(sbox.ospath('dir/file'))
+ sbox.simple_update(revision=2)
+ is_readonly(sbox.ospath('dir/file'))
+
+def update_add_file_has_lock(sbox):
+ "update adding svn:needs-lock file with lock"
+
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('test\n', 'dir/file')
+ sbox.simple_propset('svn:needs-lock', 'yes', 'dir/file')
+ sbox.simple_commit()
+
+ # Acquire the lock for a file.
+ svntest.actions.run_and_verify_svn(".*locked by user", [], 'lock',
+ '-m', '', sbox.ospath('dir/file'))
+
+ sbox.simple_update(revision=0)
+ sbox.simple_update(revision=1)
+ # We have a lock for that file, so it should be writable.
+ is_writable(sbox.ospath('dir/file'))
+
+def update_edit_file_has_lock(sbox):
+ "update editing svn:needs-lock file with lock"
+
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('test\n', 'dir/file')
+ sbox.simple_commit()
+
+ sbox.simple_append('dir/file', 'edited\n', truncate=True)
+ sbox.simple_propset('svn:needs-lock', 'yes', 'dir/file')
+ sbox.simple_commit()
+
+ # Acquire the lock for a file.
+ svntest.actions.run_and_verify_svn(".*locked by user", [], 'lock',
+ '-m', '', sbox.ospath('dir/file'))
+
+ sbox.simple_update(revision=1)
+ # No svn:needs-lock on the file, so it should be writable.
+ is_writable(sbox.ospath('dir/file'))
+ sbox.simple_update(revision=2)
+ # We have a lock for that file, so it should be writable.
+ is_writable(sbox.ospath('dir/file'))
+
+def update_remove_needs_lock(sbox):
+ "update removing svn:needs-lock on a file"
+
+ sbox.build(empty=True)
+ sbox.simple_mkdir('dir')
+ sbox.simple_add_text('test\n', 'dir/file')
+ sbox.simple_propset('svn:needs-lock', 'yes', 'dir/file')
+ sbox.simple_commit()
+
+ sbox.simple_propdel('svn:needs-lock', 'dir/file')
+ sbox.simple_commit()
+
+ sbox.simple_update(revision=1)
+ is_readonly(sbox.ospath('dir/file'))
+ sbox.simple_update(revision=2)
+ is_writable(sbox.ospath('dir/file'))
+
########################################################################
# Run the tests
@@ -2547,6 +2635,11 @@ test_list = [ None,
delete_dir_with_lots_of_locked_files,
delete_locks_on_depth_commit,
replace_dir_with_lots_of_locked_files,
+ update_add_file_needs_lock,
+ update_edit_file_needs_lock,
+ update_add_file_has_lock,
+ update_edit_file_has_lock,
+ update_remove_needs_lock,
]
if __name__ == '__main__':
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/log_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/log_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/log_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/log_tests.py Fri Jan 14 14:01:45 2022
@@ -2094,7 +2094,7 @@ def merge_sensitive_log_copied_path_inhe
svntest.main.run_svn(None, 'move', old_gamma_path, new_gamma_path)
sbox.simple_commit(message='Move file')
- # 'svn log -g --stop-on-copy ^/A/C/gamma' hould return *only* r5
+ # 'svn log -g --stop-on-copy ^/A/C/gamma' should return *only* r5
# Previously this test failed because the change in gamma's inherited
# mergeinfo between r4 and r5, due to the move, was understood as a merge:
#
@@ -2779,6 +2779,42 @@ def log_on_deleted_deep(sbox):
'',
'-q', '-c', '1-2')
+@XFail()
+@Issue(4711)
+def log_with_merge_history_and_search(sbox):
+ "log --use-merge-history --search"
+
+ sbox.build()
+
+ # r2: create branch
+ sbox.simple_repo_copy('A', 'A2') # r2
+
+ # r3: mod in trunk
+ sbox.simple_append('A/mu', 'line 2')
+ sbox.simple_commit(message='r3: mod')
+ sbox.simple_update()
+
+ # r4: merge
+ svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', sbox.ospath('A2'))
+ sbox.simple_commit(message='r4: merge')
+ sbox.simple_update()
+
+ # Helper function
+ def count(haystack, needle):
+ """Return the number of times the string NEEDLE occurs in the string
+ HAYSTACK."""
+ return len(haystack.split(needle)) - 1
+
+ # Check the output is valid
+ # ### Since the test is currently XFail, we only smoke test the output.
+ # ### When fixing this test to PASS, extend this validation.
+ _, output, _ = svntest.main.run_svn(None, 'log', '--xml', '-g',
+ '--search', "this will have no matches",
+ sbox.ospath('A2'))
+
+ output = '\n'.join(output)
+ if count(output, "<logentry") != count(output, "</logentry"):
+ raise svntest.Failure("Apparently invalid XML in " + repr(output))
########################################################################
# Run the tests
@@ -2830,6 +2866,7 @@ test_list = [ None,
merge_sensitive_log_xml_reverse_merges,
log_revision_move_copy,
log_on_deleted_deep,
+ log_with_merge_history_and_search,
]
if __name__ == '__main__':
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_authz_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_authz_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_authz_tests.py Fri Jan 14 14:01:45 2022
@@ -97,7 +97,7 @@ def mergeinfo_and_skipped_paths(sbox):
wc_disk, wc_status = set_up_branch(sbox, False, 3)
# Create a restrictive authz where part of the merge source and part
- # of the target are inaccesible.
+ # of the target are inaccessible.
write_restrictive_svnserve_conf(sbox.repo_dir)
write_authz_file(sbox, {"/" : svntest.main.wc_author +"=rw",
# Make a directory in the merge source inaccessible.
@@ -342,7 +342,7 @@ def mergeinfo_and_skipped_paths(sbox):
# this.
#
# Merge -c5 -c8 to the restricted WC's A_COPY_2/D/H. r5 gets merged first
- # but is a no-op, r8 get's merged next and is operative so the mergeinfo
+ # but is a no-op, r8 gets merged next and is operative so the mergeinfo
# should be updated on the merge target to reflect both merges.
expected_output = wc.State(A_COPY_2_H_path, {
'omega' : Item(status='U '),
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_reintegrate_tests.py Fri Jan 14 14:01:45 2022
@@ -1508,7 +1508,7 @@ def reintegrate_with_subtree_mergeinfo(s
# is all quite ugly as the intersection or multiple known issues
# is likely to be. However, given that none of this mergeinfo is
# particularly harmful and that this test is *not* about issues #3669
- # or #4309, we are tolerting it.
+ # or #4309, we are tolerating it.
'D/gamma_moved' : Item(
"Even newer content", props={SVN_PROP_MERGEINFO :
'/A/D/gamma_moved:2-7,9-12\n'
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tests.py Fri Jan 14 14:01:45 2022
@@ -3323,15 +3323,11 @@ def merge_conflict_markers_matching_eol(
mu_path = sbox.ospath('A/mu')
- # CRLF is a string that will match a CRLF sequence read from a text file.
- # ### On Windows, we assume CRLF will be read as LF, so it's a poor test.
if os.name == 'nt':
- crlf = '\n'
+ native_nl = '\r\n'
else:
- crlf = '\r\n'
-
- # Strict EOL style matching breaks Windows tests at least with Python 2
- keep_eol_style = not svntest.main.is_os_windows()
+ native_nl = '\n'
+ crlf = '\r\n'
# Checkout a second working copy
wc_backup = sbox.add_wc_path('backup')
@@ -3349,8 +3345,8 @@ def merge_conflict_markers_matching_eol(
path_backup = os.path.join(wc_backup, 'A', 'mu')
# do the test for each eol-style
- for eol, eolchar in zip(['CRLF', 'CR', 'native', 'LF'],
- [crlf, '\015', '\n', '\012']):
+ for eol, eolchar in zip(['CRLF', 'CR','native', 'LF'],
+ [crlf, '\015', native_nl, '\012']):
# rewrite file mu and set the eol-style property.
svntest.main.file_write(mu_path, "This is the file 'mu'."+ eolchar, 'wb')
svntest.main.run_svn(None, 'propset', 'svn:eol-style', eol, mu_path)
@@ -3375,8 +3371,8 @@ def merge_conflict_markers_matching_eol(
svntest.main.run_svn(None, 'update', wc_backup)
# Make a local mod to mu
- svntest.main.file_append(mu_path,
- 'Original appended text for mu' + eolchar)
+ svntest.main.file_append_binary(mu_path,
+ 'Original appended text for mu' + eolchar)
# Commit the original change and note the 'theirs' revision number
svntest.main.run_svn(None, 'commit', '-m', 'test log', wc_dir)
@@ -3384,8 +3380,9 @@ def merge_conflict_markers_matching_eol(
theirs_rev = cur_rev
# Make a local mod to mu, will conflict with the previous change
- svntest.main.file_append(path_backup,
- 'Conflicting appended text for mu' + eolchar)
+ svntest.main.file_append_binary(path_backup,
+ 'Conflicting appended text for mu'
+ + eolchar)
# Create expected output tree for an update of the wc_backup.
expected_backup_output = svntest.wc.State(wc_backup, {
@@ -3445,7 +3442,7 @@ def merge_conflict_markers_matching_eol(
expected_backup_disk,
expected_backup_status,
expected_backup_skip,
- keep_eol_style=keep_eol_style)
+ keep_eol_style=True)
# cleanup for next run
svntest.main.run_svn(None, 'revert', '-R', wc_backup)
@@ -3468,15 +3465,7 @@ def merge_eolstyle_handling(sbox):
mu_path = sbox.ospath('A/mu')
- # CRLF is a string that will match a CRLF sequence read from a text file.
- # ### On Windows, we assume CRLF will be read as LF, so it's a poor test.
- if os.name == 'nt':
- crlf = '\n'
- else:
- crlf = '\r\n'
-
- # Strict EOL style matching breaks Windows tests at least with Python 2
- keep_eol_style = not svntest.main.is_os_windows()
+ crlf = '\r\n'
# Checkout a second working copy
wc_backup = sbox.add_wc_path('backup')
@@ -3518,7 +3507,7 @@ def merge_eolstyle_handling(sbox):
expected_backup_disk,
expected_backup_status,
expected_backup_skip,
- keep_eol_style=keep_eol_style)
+ keep_eol_style=True)
# Test 2: now change the eol-style property to another value and commit,
# merge this revision in the still changed mu in the second working copy;
@@ -3549,7 +3538,7 @@ def merge_eolstyle_handling(sbox):
expected_backup_disk,
expected_backup_status,
expected_backup_skip,
- keep_eol_style=keep_eol_style)
+ keep_eol_style=True)
# Test 3: now delete the eol-style property and commit, merge this revision
# in the still changed mu in the second working copy; there should be no
@@ -3578,7 +3567,7 @@ def merge_eolstyle_handling(sbox):
expected_backup_disk,
expected_backup_status,
expected_backup_skip,
- keep_eol_style=keep_eol_style)
+ keep_eol_style=True)
#----------------------------------------------------------------------
def create_deep_trees(wc_dir):
@@ -4794,7 +4783,7 @@ def mergeinfo_inheritance_and_discontinu
# Merge r2:6 into A_COPY/D
#
# A_COPY/D should inherit the mergeinfo '/A:4' from A_COPY
- # combine it with the discontinous merges performed directly on
+ # combine it with the discontinuous merges performed directly on
# it (A/D/ 2:3 and A/D 4:6) resulting in '/A/D:3-6'.
expected_output = wc.State(D_COPY_path, {
'H/psi' : Item(status='U '),
@@ -4966,11 +4955,11 @@ def merge_to_switched_path(sbox):
A_COPY_D_G_rho_path = sbox.ospath('A_COPY/D/G/rho')
expected = svntest.verify.UnorderedOutput(
- ["A " + os.path.join(G_COPY_path, "pi") + "\n",
- "A " + os.path.join(G_COPY_path, "rho") + "\n",
- "A " + os.path.join(G_COPY_path, "tau") + "\n",
- "Checked out revision 6.\n",
- "A " + G_COPY_path + "\n"])
+ ["A " + G_COPY_path + "\n",
+ "A " + os.path.join(G_COPY_path, "pi") + "\n",
+ "A " + os.path.join(G_COPY_path, "rho") + "\n",
+ "A " + os.path.join(G_COPY_path, "tau") + "\n",
+ ])
# r7 - Copy A/D/G to A/D/G_COPY and commit.
svntest.actions.run_and_verify_svn(expected, [], 'copy',
@@ -12848,6 +12837,39 @@ def natural_history_filtering(sbox):
# the revisions on 'trunk' which occurred after 'branch2' was copied as
# these are not part of 'branch2's natural history.
+ def path_join(head, tail):
+ if not head: return tail
+ if not tail: return head
+ return head + '/' + tail
+
+ def greek_file_item(path):
+ if path[-1:].islower():
+ basename = re.sub('.*/', '', path)
+ return Item("This is the file '" + basename + "'.\n")
+ return Item()
+
+ A_paths = [
+ "",
+ "B",
+ "B/lambda",
+ "B/E",
+ "B/E/alpha",
+ "B/E/beta",
+ "B/F",
+ "mu",
+ "C",
+ "D",
+ "D/gamma",
+ "D/G",
+ "D/G/pi",
+ "D/G/rho",
+ "D/G/tau",
+ "D/H",
+ "D/H/chi",
+ "D/H/omega",
+ "D/H/psi",
+ ]
+
sbox.build()
wc_dir = sbox.wc_dir
@@ -12861,68 +12883,16 @@ def natural_history_filtering(sbox):
# r7: Make a second 'branch': Copy A to A_COPY_2
expected = svntest.verify.UnorderedOutput(
- ["A " + os.path.join(A_COPY_2_path, "B") + "\n",
- "A " + os.path.join(A_COPY_2_path, "B", "lambda") + "\n",
- "A " + os.path.join(A_COPY_2_path, "B", "E") + "\n",
- "A " + os.path.join(A_COPY_2_path, "B", "E", "alpha") + "\n",
- "A " + os.path.join(A_COPY_2_path, "B", "E", "beta") + "\n",
- "A " + os.path.join(A_COPY_2_path, "B", "F") + "\n",
- "A " + os.path.join(A_COPY_2_path, "mu") + "\n",
- "A " + os.path.join(A_COPY_2_path, "C") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "gamma") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "G") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "G", "pi") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "G", "rho") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "G", "tau") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "H") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "H", "chi") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "H", "omega") + "\n",
- "A " + os.path.join(A_COPY_2_path, "D", "H", "psi") + "\n",
- "Checked out revision 6.\n",
- "A " + A_COPY_2_path + "\n"])
- wc_status.add({
- "A_COPY_2" + "/B" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/B/lambda" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/B/E" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/B/E/alpha" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/B/E/beta" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/B/F" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/mu" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/C" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/gamma" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/G" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/G/pi" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/G/rho" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/G/tau" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/H" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/H/chi" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/H/omega" : Item(status=' ', wc_rev=7),
- "A_COPY_2" + "/D/H/psi" : Item(status=' ', wc_rev=7),
- "A_COPY_2" : Item(status=' ', wc_rev=7),
- })
- wc_disk.add({
- "A_COPY_2" : Item(),
- "A_COPY_2" + '/B' : Item(),
- "A_COPY_2" + '/B/lambda' : Item("This is the file 'lambda'.\n"),
- "A_COPY_2" + '/B/E' : Item(),
- "A_COPY_2" + '/B/E/alpha' : Item("This is the file 'alpha'.\n"),
- "A_COPY_2" + '/B/E/beta' : Item("New content"),
- "A_COPY_2" + '/B/F' : Item(),
- "A_COPY_2" + '/mu' : Item("This is the file 'mu'.\n"),
- "A_COPY_2" + '/C' : Item(),
- "A_COPY_2" + '/D' : Item(),
- "A_COPY_2" + '/D/gamma' : Item("This is the file 'gamma'.\n"),
- "A_COPY_2" + '/D/G' : Item(),
- "A_COPY_2" + '/D/G/pi' : Item("This is the file 'pi'.\n"),
- "A_COPY_2" + '/D/G/rho' : Item("New content"),
- "A_COPY_2" + '/D/G/tau' : Item("This is the file 'tau'.\n"),
- "A_COPY_2" + '/D/H' : Item(),
- "A_COPY_2" + '/D/H/chi' : Item("New content"),
- "A_COPY_2" + '/D/H/omega' : Item("This is the file 'omega'.\n"),
- "A_COPY_2" + '/D/H/psi' : Item("New content"),
- })
+ [ "A " + sbox.ospath(path_join("A_COPY_2", p)) + "\n"
+ for p in A_paths ])
+ wc_status.add(
+ { path_join("A_COPY_2", p) : Item(status=' ', wc_rev=7)
+ for p in A_paths })
+ wc_disk.add(
+ { path_join("A_COPY_2", p) :
+ Item("New content") if p in ['B/E/beta', 'D/G/rho', 'D/H/chi', 'D/H/psi']
+ else greek_file_item(p)
+ for p in A_paths })
svntest.actions.run_and_verify_svn(expected, [], 'copy',
sbox.repo_url + "/A",
A_COPY_2_path)
@@ -13380,7 +13350,7 @@ def no_self_referential_filtering_on_add
def merge_range_prior_to_rename_source_existence(sbox):
"merge prior to rename src existence still dels src"
- # Replicate a merge bug found while synching up a feature branch on the
+ # Replicate a merge bug found while syncing up a feature branch on the
# Subversion repository with trunk. See r874121 of
# http://svn.apache.org/repos/asf/subversion/branches/ignore-mergeinfo, in which
# a move was merged to the target, but the delete half of the move
@@ -18530,6 +18500,276 @@ def merge_dir_delete_force(sbox):
'merge', '-c2', '^/', sbox.wc_dir,
'--ignore-ancestry', '--force')
+# Issue #4859: Merge removing a folder with non-inheritable mergeinfo ->
+# E155023: can't set properties: invalid status for updating properties
+@Issue(4859)
+def merge_deleted_folder_with_mergeinfo(sbox):
+ "merge deleted folder with mergeinfo"
+
+ sbox.build()
+
+ was_cwd = os.getcwd()
+ os.chdir(sbox.wc_dir)
+ sbox.wc_dir = ''
+
+ # Some non-inheritable mergeinfo
+ sbox.simple_propset('svn:mergeinfo', '/A/C:1*', 'A/D')
+ sbox.simple_commit() # r2
+
+ # Branching
+ sbox.simple_repo_copy('A', 'branch_A') # r3
+ sbox.simple_update()
+
+ # On branch, remove a folder that has non-inheritable mergeinfo
+ sbox.simple_rm('branch_A/D')
+ sbox.simple_commit() # r4
+
+ sbox.simple_update()
+
+ # A merge that removes that folder
+ # (merge revision 4 only from 'branch_A' to 'A')
+ expected_output = wc.State(sbox.ospath(''), {
+ 'A/D' : Item(status='D '),
+ })
+ expected_mergeinfo_output = wc.State(sbox.ospath(''), {
+ 'A' : Item(status=' U'),
+ })
+ expected_status = svntest.actions.get_virginal_state(sbox.ospath('A'), 4).subtree('A')
+ expected_status.add({ '': Item(status=' M', wc_rev=4) })
+ expected_status.tweak_some(
+ lambda path, item: [True] if path.split('/')[0] == 'D' else [],
+ status='D ')
+ svntest.actions.run_and_verify_merge(sbox.ospath('A'), 3, 4,
+ '^/branch_A', None,
+ expected_output,
+ expected_mergeinfo_output,
+ None,
+ None,
+ expected_status,
+ wc.State('', {}),
+ [],
+ check_props=False,
+ dry_run=False # as dry run is broken
+ )
+
+ os.chdir(was_cwd)
+
+# Issue #4859: Merge removing a folder with non-inheritable mergeinfo ->
+# E155023: can't set properties: invalid status for updating properties
+#
+# In this test we split the merge into two separate operable parts, a
+# delete followed later by an add, to check it will set the mergeinfo on the
+# subtree paths if the deleted folder is later replaced within the same
+# overall merge.
+@Issue(4859)
+def merge_deleted_folder_with_mergeinfo_2(sbox):
+ "merge deleted folder with mergeinfo 2"
+
+ sbox.build()
+
+ was_cwd = os.getcwd()
+ os.chdir(sbox.wc_dir)
+ sbox.wc_dir = ''
+
+ # Some non-inheritable mergeinfo
+ sbox.simple_propset('svn:mergeinfo', '/A/C:1*', 'A/D')
+ sbox.simple_commit() # r2
+
+ # Branching
+ sbox.simple_repo_copy('A', 'branch_A') # r3
+ sbox.simple_update()
+
+ # On branch, remove a folder that has non-inheritable mergeinfo
+ sbox.simple_rm('branch_A/D')
+ sbox.simple_commit() # r4
+
+ # A commit that we don't want to merge from the branch, to split the merge
+ # into two separate operable parts.
+ sbox.simple_mkdir('branch_A/IgnoreThis')
+ sbox.simple_commit() # r5
+
+ # On branch, replace the deleted folder with a new one, with mergeinfo,
+ # to check we don't omit setting mergeinfo on this.
+ sbox.simple_mkdir('branch_A/D')
+ sbox.simple_propset('svn:mergeinfo', '/branch_B/C:1*', 'branch_A/D')
+ sbox.simple_mkdir('branch_A/D/G', 'branch_A/D/G2')
+ sbox.simple_propset('svn:mergeinfo', '/branch_B/C/G:1*', 'branch_A/D/G')
+ sbox.simple_propset('svn:mergeinfo', '/branch_B/C/G2:1*', 'branch_A/D/G2')
+ sbox.simple_commit() # r6
+
+ sbox.simple_propset('svn:mergeinfo', '/branch_A:5', 'A')
+ sbox.simple_commit() # r7
+
+ sbox.simple_update()
+
+ # A merge that removes that folder
+ expected_output = wc.State(sbox.ospath(''), {
+ 'A/D' : Item(status='A ', prev_status='D '),
+ 'A/D/G' : Item(status='A '),
+ 'A/D/G2' : Item(status='A '),
+ })
+ # verify that mergeinfo is set/changed on A/D, A/D/G, A/D/G2.
+ expected_mergeinfo_output = wc.State(sbox.ospath(''), {
+ 'A' : Item(status=' U'),
+ 'A/D' : Item(status=' G'),
+ 'A/D/G' : Item(status=' G'),
+ 'A/D/G2' : Item(status=' G'),
+ })
+ expected_status = svntest.actions.get_virginal_state(sbox.ospath('A'), 7).subtree('A')
+ expected_status.tweak_some(
+ lambda path, item: [True] if path.split('/')[0] == 'D' else [],
+ status='D ')
+ expected_status.add({
+ '' : Item(status=' M', wc_rev=7),
+ 'D' : Item(status='RM', copied='+', wc_rev='-'),
+ 'D/G' : Item(status=' M', copied='+', wc_rev='-'),
+ 'D/G2' : Item(status=' M', copied='+', wc_rev='-'),
+ })
+ svntest.actions.run_and_verify_merge(sbox.ospath('A'), None, None,
+ '^/branch_A', None,
+ expected_output,
+ expected_mergeinfo_output,
+ None,
+ None,
+ expected_status,
+ wc.State('', {}),
+ [],
+ check_props=False,
+ dry_run=False # as dry run is broken
+ )
+
+ # verify that mergeinfo is set/changed on A/D, A/D/G, A/D/G2.
+
+ # NOTE: When writing out multi-line prop values in svn:* props, the
+ # client converts to local encoding and local eol style.
+ # Therefore, the expected output must contain the right kind of eoln
+ # strings. That's why we use os.linesep in the tests below, not just
+ # plain '\n'.
+
+ expected_mergeinfo = [
+ ('A', ['/branch_A:3-7']),
+ ('A/D', ['/branch_A/D:5-7'+os.linesep, '/branch_B/C:1*']),
+ ('A/D/G', ['/branch_A/D/G:5-7'+os.linesep, '/branch_B/C/G:1*']),
+ ('A/D/G2', ['/branch_A/D/G2:5-7'+os.linesep, '/branch_B/C/G2:1*']),
+ ]
+ for path, mergeinfo in expected_mergeinfo:
+ svntest.actions.check_prop('svn:mergeinfo', sbox.ospath(path),
+ [m.encode() for m in mergeinfo])
+
+ os.chdir(was_cwd)
+
+#----------------------------------------------------------------------
+# Test that mismatched source repository root URLs in a two-URL merge
+# throws an error E170000 SVN_ERR_RA_ILLEGAL_URL.
+#
+# (Since issue 4874 (Subversion 1.15) that error is also wrapped in
+# E195012 SVN_ERR_CLIENT_UNRELATED_RESOURCES for consistency with
+# the source-target mismatch errors.)
+#
+# For mismatched URLs we use two repositories with the same UUID.
+@Issue(4874)
+def merge_error_if_source_urls_differ(sbox):
+ "merge error if source urls differ"
+
+ sbox.build()
+ expected_disk, expected_status = set_up_branch(sbox)
+ wc_dir = sbox.wc_dir
+ repo_dir = sbox.repo_dir
+
+ # Create a second repository with the same content, same UUID
+ other_repo_dir, other_repo_url = sbox.add_repo_path("other")
+ other_wc_dir = sbox.add_wc_path("other")
+ svntest.main.copy_repos(repo_dir, other_repo_dir, 6, ignore_uuid=False)
+
+ G_COPY_path = sbox.ospath('A_COPY/D/G')
+ svntest.actions.run_and_verify_svn2(None, '.*: E170000: .*', 1,
+ 'merge',
+ sbox.repo_url + '/A/D/G@3',
+ other_repo_url + '/A/D/G@4',
+ G_COPY_path)
+
+#----------------------------------------------------------------------
+# Test that a merge with mismatched source and target repository root URLs
+# but identical repository UUIDs throws a warning error, for two-URL and
+# pegged merges.
+#
+# Issue #4874 makes this a warning in Subversion 1.15 and an error in 1.16.
+# Previously it was treated as a foreign repository merge.
+#
+# For mismatched URLs we use two repositories with the same UUID.
+@Issue(4874)
+def merge_error_if_ambiguous_foreign_merge(sbox):
+ "merge error if ambiguous foreign merge"
+
+ sbox.build()
+ expected_disk, expected_status = set_up_branch(sbox)
+ wc_dir = sbox.wc_dir
+ repo_dir = sbox.repo_dir
+
+ # Create a second repository with the same content, same UUID
+ other_repo_dir, other_repo_url = sbox.add_repo_path("other")
+ other_wc_dir = sbox.add_wc_path("other")
+ svntest.main.copy_repos(repo_dir, other_repo_dir, 6, ignore_uuid=False)
+
+ # With Issue #4874 implemented, the attempted merges should error out with
+ # SVN_ERR_CLIENT_UNRELATED_RESOURCES, because of mismatched source and
+ # target URLs.
+
+ # expect warning or error (E195012 SVN_ERR_CLIENT_UNRELATED_RESOURCES)?
+ expected_stdout = None if svntest.main.SVN_VER_MINOR < 16 else []
+ expected_stderr = '.*: E195012: .*' if svntest.main.SVN_VER_MINOR >= 15 else []
+ expected_exit = 0 if svntest.main.SVN_VER_MINOR < 16 else 1
+
+ # two-URL merge
+ svntest.actions.run_and_verify_svn2(expected_stdout, expected_stderr,
+ expected_exit,
+ 'merge',
+ other_repo_url + '/A/D/G@3',
+ other_repo_url + '/A/D/G@4',
+ sbox.ospath('A_COPY/D/G'))
+ svntest.main.run_svn(False, 'revert', '-qR', sbox.wc_dir)
+ # pegged merge
+ svntest.actions.run_and_verify_svn2(expected_stdout, expected_stderr,
+ expected_exit,
+ 'merge', '-c4',
+ other_repo_url + '/A/D/G',
+ sbox.ospath('A_COPY/D/G'))
+ svntest.main.run_svn(False, 'revert', '-qR', sbox.wc_dir)
+
+#----------------------------------------------------------------------
+# Test that a merge with mismatched source and target repository root URLs
+# throws an error, for automatic and reintegrate merges.
+#
+# This behaviour is unchanged by issue #4874, just reinforced and with more
+# informative error messages.
+#
+# For mismatched URLs we use two repositories with the same UUID.
+@Issue(4874)
+def merge_error_if_source_target_url_mismatch(sbox):
+ "merge error if source target url mismatch"
+
+ sbox.build()
+ expected_disk, expected_status = set_up_branch(sbox)
+ wc_dir = sbox.wc_dir
+ repo_dir = sbox.repo_dir
+
+ # Create a second repository with the same content, same UUID
+ other_repo_dir, other_repo_url = sbox.add_repo_path("other")
+ other_wc_dir = sbox.add_wc_path("other")
+ svntest.main.copy_repos(repo_dir, other_repo_dir, 6, ignore_uuid=False)
+
+ expected_stderr = '.*: E195012: .*' # SVN_ERR_CLIENT_UNRELATED_RESOURCES
+ # automatic merge
+ svntest.actions.run_and_verify_svn2([], expected_stderr, 1,
+ 'merge',
+ other_repo_url + '/A/D/G',
+ sbox.ospath('A_COPY/D/G'))
+ # reintegrate merge
+ svntest.actions.run_and_verify_svn2([], expected_stderr, 1,
+ 'merge', '--reintegrate',
+ other_repo_url + '/A/D/G',
+ sbox.ospath('A_COPY/D/G'))
+
########################################################################
# Run the tests
@@ -18677,6 +18917,11 @@ test_list = [ None,
merge_to_empty_target_merge_to_infinite_target,
conflict_naming,
merge_dir_delete_force,
+ merge_deleted_folder_with_mergeinfo,
+ merge_deleted_folder_with_mergeinfo_2,
+ merge_error_if_source_urls_differ,
+ merge_error_if_ambiguous_foreign_merge,
+ merge_error_if_source_target_url_mismatch,
]
if __name__ == '__main__':
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tree_conflict_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/merge_tree_conflict_tests.py Fri Jan 14 14:01:45 2022
@@ -2364,6 +2364,233 @@ def spurios_tree_conflict_with_added_fil
[], False, True, '--reintegrate',
sbox.ospath('A_branch'))
+def merge_local_missing_node_kind_none(sbox):
+ "crash in resolver triggered by none-type node"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ sbox.simple_mkdir('branches')
+ sbox.simple_commit() # r2
+ sbox.simple_update()
+
+ # Create a feature branch of A
+ sbox.simple_copy('A', 'branches/feature1')
+ sbox.simple_commit() #r3
+ sbox.simple_update()
+
+ # On the branch, move file alpha to another directory
+ sbox.simple_move('branches/feature1/B/E/alpha',
+ 'branches/feature1/D/H/alpha-from-B-E')
+ sbox.simple_commit() # r4
+ sbox.simple_update()
+
+ # Cherry-pick the delete-half of the above move into A (the trunk)
+ expected_output = svntest.wc.State(sbox.ospath('A/B/E'), {
+ 'alpha' : Item(status='D '),
+ })
+ expected_mergeinfo_output = wc.State(sbox.ospath('A/B/E'), {
+ '' : Item(status=' U')
+ })
+ expected_elision_output = wc.State(wc_dir, {
+ })
+ expected_disk = wc.State('', {
+ 'beta' : Item(contents="This is the file 'beta'.\n"),
+ '.' : Item(props={u'svn:mergeinfo':
+ u'/branches/feature1/B/E:4'}),
+ })
+ expected_status = wc.State(sbox.ospath('A/B/E'), {
+ '' : Item(status=' M', wc_rev='4'),
+ 'alpha' : Item(status='D ', wc_rev='4'),
+ 'beta' : Item(status=' ', wc_rev='4'),
+ })
+ expected_skip = wc.State('', {
+ })
+ svntest.actions.run_and_verify_merge(sbox.ospath('A/B/E'), 3, 4,
+ sbox.repo_url + '/branches/feature1/B/E',
+ None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ check_props=True)
+ sbox.simple_commit() # r5
+ sbox.simple_update()
+
+ # Create a new file on the feature branch
+ sbox.simple_add_text("This is the file 'pi'\n", 'branches/feature1/B/E/pi')
+ sbox.simple_commit() #r6
+ sbox.simple_update()
+
+ # Create a second branch based on the feature branch.
+ sbox.simple_copy('branches/feature1', 'branches/feature2')
+ sbox.simple_commit() #r7
+ sbox.simple_update()
+
+ # Create a new file kappa on this second branch
+ sbox.simple_add_text("This is the file 'kappa'\n",
+ 'branches/feature2/B/E/kappa')
+ sbox.simple_commit() #r8
+ sbox.simple_update()
+
+ # An unrelated additional change on the second branch.
+ sbox.simple_append('branches/feature2/B/E/beta',
+ "This is a change to file 'beta'.\n")
+ sbox.simple_commit() #r9
+ sbox.simple_update()
+
+ # Merge the second branch back into the feature branch
+ expected_output = svntest.wc.State(sbox.ospath('branches/feature1'), {
+ 'B/E/kappa' : Item(status='A '),
+ 'B/E/beta' : Item(status='U '),
+ })
+ expected_mergeinfo_output = wc.State(sbox.ospath('branches/feature1'), {
+ '.' : Item(status=' U'),
+ })
+ expected_elision_output = wc.State(wc_dir, {
+ })
+ expected_disk = wc.State('', {
+ 'C' : Item(),
+ 'B/E/kappa' : Item(contents="This is the file 'kappa'\n"),
+ 'B/E/pi' : Item(contents="This is the file 'pi'\n"),
+ 'B/E/beta' : Item(contents="This is the file 'beta'.\n" +
+ "This is a change to file 'beta'.\n"),
+ 'B/lambda' : Item(contents="This is the file 'lambda'.\n"),
+ 'B/F' : Item(),
+ 'D/H/omega' : Item(contents="This is the file 'omega'.\n"),
+ 'D/H/alpha-from-B-E': Item(contents="This is the file 'alpha'.\n"),
+ 'D/H/psi' : Item(contents="This is the file 'psi'.\n"),
+ 'D/H/chi' : Item(contents="This is the file 'chi'.\n"),
+ 'D/G/pi' : Item(contents="This is the file 'pi'.\n"),
+ 'D/G/rho' : Item(contents="This is the file 'rho'.\n"),
+ 'D/G/tau' : Item(contents="This is the file 'tau'.\n"),
+ 'D/gamma' : Item(contents="This is the file 'gamma'.\n"),
+ 'mu' : Item(contents="This is the file 'mu'.\n"),
+ '.' : Item(props={u'svn:mergeinfo':
+ u'/branches/feature2:7-9'}),
+ })
+ expected_status = wc.State(sbox.ospath('branches/feature1'), {
+ '' : Item(status=' M', wc_rev='9'),
+ 'mu' : Item(status=' ', wc_rev='9'),
+ 'D' : Item(status=' ', wc_rev='9'),
+ 'D/H' : Item(status=' ', wc_rev='9'),
+ 'D/H/alpha-from-B-E': Item(status=' ', wc_rev='9'),
+ 'D/H/psi' : Item(status=' ', wc_rev='9'),
+ 'D/H/chi' : Item(status=' ', wc_rev='9'),
+ 'D/H/omega' : Item(status=' ', wc_rev='9'),
+ 'D/G' : Item(status=' ', wc_rev='9'),
+ 'D/G/pi' : Item(status=' ', wc_rev='9'),
+ 'D/G/tau' : Item(status=' ', wc_rev='9'),
+ 'D/G/rho' : Item(status=' ', wc_rev='9'),
+ 'D/gamma' : Item(status=' ', wc_rev='9'),
+ 'B' : Item(status=' ', wc_rev='9'),
+ 'B/E' : Item(status=' ', wc_rev='9'),
+ 'B/E/beta' : Item(status='M ', wc_rev='9'),
+ 'B/E/kappa' : Item(status='A ', copied='+', wc_rev='-'),
+ 'B/E/pi' : Item(status=' ', wc_rev='9'),
+ 'B/lambda' : Item(status=' ', wc_rev='9'),
+ 'B/F' : Item(status=' ', wc_rev='9'),
+ 'C' : Item(status=' ', wc_rev='9'),
+ })
+ expected_skip = wc.State('', {
+ })
+ svntest.actions.run_and_verify_merge(sbox.ospath('branches/feature1'),
+ None, None,
+ sbox.repo_url + '/branches/feature2',
+ None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ check_props=True)
+ sbox.simple_commit() # r10
+ sbox.simple_update()
+
+ # On the feature branch, rename the file kappa
+ sbox.simple_move('branches/feature1/B/E/kappa',
+ 'branches/feature1/B/E/kappanew')
+ sbox.simple_commit() # r11
+ sbox.simple_update()
+
+ # On the feature branch, move file kappanew to another directory
+ sbox.simple_move('branches/feature1/B/E/kappanew',
+ 'branches/feature1/D/H/kappanew')
+ sbox.simple_commit() # r12
+ sbox.simple_update()
+
+ # Cherry-pick r12 into A (the trunk)
+ # This triggers an assertion failure in Subversion 1.14.1 because of
+ # a node type lookup which uses the wrong token map:
+ # W: subversion/libsvn_subr/token.c:40: (apr_err=SVN_ERR_ASSERTION_FAIL)
+ # svn: E235000: In file 'subversion/libsvn_subr/token.c' line 40: internal malfunction
+ expected_output = svntest.wc.State(sbox.ospath('A'), {
+ 'B/E/kappanew' : Item(status=' ', treeconflict='C'),
+ 'D/H/kappanew' : Item(status='A '),
+ })
+ expected_mergeinfo_output = wc.State(sbox.ospath('A'), {
+ '' : Item(status=' U'),
+ 'B/E' : Item(status=' U'),
+ })
+ expected_elision_output = wc.State(wc_dir, {
+ })
+ expected_disk = wc.State('', {
+ 'C' : Item(),
+ 'B/E' : Item(props={u'svn:mergeinfo':
+ u'/branches/feature1/B/E:4,12'}),
+ 'B/E/beta' : Item(contents="This is the file 'beta'.\n"),
+ 'B/lambda' : Item(contents="This is the file 'lambda'.\n"),
+ 'B/F' : Item(),
+ 'D/H/omega' : Item(contents="This is the file 'omega'.\n"),
+ 'D/H/kappanew' : Item(contents="This is the file 'kappa'\n"),
+ 'D/H/psi' : Item(contents="This is the file 'psi'.\n"),
+ 'D/H/chi' : Item(contents="This is the file 'chi'.\n"),
+ 'D/G/pi' : Item(contents="This is the file 'pi'.\n"),
+ 'D/G/rho' : Item(contents="This is the file 'rho'.\n"),
+ 'D/G/tau' : Item(contents="This is the file 'tau'.\n"),
+ 'D/gamma' : Item(contents="This is the file 'gamma'.\n"),
+ 'mu' : Item(contents="This is the file 'mu'.\n"),
+ '.' : Item(props={u'svn:mergeinfo':
+ u'/branches/feature1:12'}),
+ })
+ expected_status = wc.State(sbox.ospath('A'), {
+ '' : Item(status=' M', wc_rev='12'),
+ 'D' : Item(status=' ', wc_rev='12'),
+ 'D/H' : Item(status=' ', wc_rev='12'),
+ 'D/H/chi' : Item(status=' ', wc_rev='12'),
+ 'D/H/psi' : Item(status=' ', wc_rev='12'),
+ 'D/H/kappanew' : Item(status='A ', copied='+', wc_rev='-'),
+ 'D/H/omega' : Item(status=' ', wc_rev='12'),
+ 'D/G' : Item(status=' ', wc_rev='12'),
+ 'D/G/pi' : Item(status=' ', wc_rev='12'),
+ 'D/G/tau' : Item(status=' ', wc_rev='12'),
+ 'D/G/rho' : Item(status=' ', wc_rev='12'),
+ 'D/gamma' : Item(status=' ', wc_rev='12'),
+ 'B' : Item(status=' ', wc_rev='12'),
+ 'B/E' : Item(status=' M', wc_rev='12'),
+ 'B/E/beta' : Item(status=' ', wc_rev='12'),
+ 'B/E/kappanew' : Item(status='! ', treeconflict='C'),
+ 'B/F' : Item(status=' ', wc_rev='12'),
+ 'B/lambda' : Item(status=' ', wc_rev='12'),
+ 'mu' : Item(status=' ', wc_rev='12'),
+ 'C' : Item(status=' ', wc_rev='12'),
+ })
+ expected_skip = wc.State('', {
+ })
+ svntest.actions.run_and_verify_merge(sbox.ospath('A'), 11, 12,
+ sbox.repo_url + '/branches/feature1',
+ None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ check_props=True)
+
########################################################################
# Run the tests
@@ -2399,6 +2626,7 @@ test_list = [ None,
merge_obstruction_recording,
added_revision_recording_in_tree_conflict,
spurios_tree_conflict_with_added_file,
+ merge_local_missing_node_kind_none,
]
if __name__ == '__main__':
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_authz_svn_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_authz_svn_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_authz_svn_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_authz_svn_tests.py Fri Jan 14 14:01:45 2022
@@ -25,7 +25,7 @@
######################################################################
# General modules
-import os, re, logging
+import os, re, logging, shutil
logger = logging.getLogger()
@@ -167,7 +167,7 @@ def anon(sbox):
write_authz_file(sbox)
- anon_tests = (
+ anon_tests = (
{ 'path': '', 'status': 301 },
{ 'path': '/', 'status': 200 },
{ 'path': '/repos', 'status': 301 },
@@ -1043,6 +1043,73 @@ def authn_sallrall(sbox):
verify_gets(test_area_url, sallrall_tests)
+@SkipUnless(svntest.main.is_ra_type_dav)
+def repos_relative_access_file(sbox):
+ "repos-relative access file"
+
+ sbox.build()
+
+ test_area_url = sbox.repo_url.replace('/svn-test-work/repositories/',
+ '/authz-test-work/in-repos-authz/')
+
+ svntest.main.write_authz_file(sbox, {"/": "", "/A": "%s = rw" % user1})
+ shutil.move(sbox.authz_file, os.path.join(sbox.wc_dir, 'authz'))
+ sbox.simple_add('authz')
+ svntest.actions.run_and_verify_svn(None, [], 'relocate',
+ sbox.file_protocol_repo_url(), sbox.wc_dir)
+ sbox.simple_commit(message="adding in-repository authz rules file")
+
+ in_repos_authz_tests = (
+ { 'path': '', 'status': 401, },
+ { 'path': '/authz', 'status': 401, },
+ { 'path': '/authz', 'user' : user1, 'pw' : user1_pass,
+ 'status': 403, },
+ { 'path': '/A', 'user' : user1, 'pw' : user1_pass,
+ 'status': 301, },
+ { 'path': '/A/', 'user' : user1, 'pw' : user1_pass,
+ 'status': 200, },
+ )
+
+ verify_gets(test_area_url, in_repos_authz_tests)
+
+# test for the bug also known as CVE-2020-17525
+@SkipUnless(svntest.main.is_ra_type_dav)
+def nonexistent_repos_relative_access_file(sbox):
+ "repos-relative access file with bad repository URL"
+
+ sbox.build()
+
+ test_area_url = sbox.repo_url.replace('/svn-test-work/repositories/',
+ '/authz-test-work/in-repos-authz/')
+
+ # Construct a bad test-area URL to see what happens if we attempt to access
+ # a repository in a subdirectory which does not exist in SVNParentPath.
+ # This used to crash the server with a NULL-pointer dereference upon
+ # unauthenticated access.
+ test_area_url += '-this/does/not/exist'
+
+ svntest.main.write_authz_file(sbox, {"/": "", "/A": "%s = rw" % user1})
+ shutil.move(sbox.authz_file, os.path.join(sbox.wc_dir, 'authz'))
+ sbox.simple_add('authz')
+ svntest.actions.run_and_verify_svn(None, [], 'relocate',
+ sbox.file_protocol_repo_url(), sbox.wc_dir)
+ sbox.simple_commit(message="adding in-repository authz rules file")
+
+ # access is denied across the board since this repository does not exist
+ in_repos_authz_tests = (
+ { 'path': '', 'status': 401, },
+ { 'path': '/authz', 'status': 401, },
+ { 'path': '/authz', 'user' : user1, 'pw' : user1_pass,
+ 'status': 403, },
+ { 'path': '/A', 'user' : user1, 'pw' : user1_pass,
+ 'status': 403, },
+ { 'path': '/A/', 'user' : user1, 'pw' : user1_pass,
+ 'status': 403, },
+ )
+
+ verify_gets(test_area_url, in_repos_authz_tests)
+
+
########################################################################
# Run the tests
@@ -1058,6 +1125,8 @@ test_list = [ None,
authn_group,
authn_sallrany,
authn_sallrall,
+ repos_relative_access_file,
+ nonexistent_repos_relative_access_file,
]
serial_only = True
Modified: subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_dav_svn_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_dav_svn_tests.py?rev=1897034&r1=1897033&r2=1897034&view=diff
==============================================================================
--- subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_dav_svn_tests.py (original)
+++ subversion/branches/multi-wc-format/subversion/tests/cmdline/mod_dav_svn_tests.py Fri Jan 14 14:01:45 2022
@@ -102,7 +102,7 @@ def compare_xml_elem(a, b):
# iteration.
def sortcmp(x, y):
return compare_xml_elem(x, y)[0]
-
+
a_children = sorted(list(a), key=functools.cmp_to_key(sortcmp))
b_children = sorted(list(b), key=functools.cmp_to_key(sortcmp))
@@ -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