You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2013/02/23 02:25:44 UTC
svn commit: r1449262 [19/25] - in /subversion/branches/ev2-export: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ build/win32/
contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/
note...
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/entries-dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/entries-dump.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/entries-dump.c (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/entries-dump.c Sat Feb 23 01:25:38 2013
@@ -38,6 +38,7 @@
#include "private/svn_wc_private.h"
#include "../../libsvn_wc/wc.h"
+#include "../../libsvn_wc/lock.h"
static void
str_value(const char *name, const char *value)
@@ -66,21 +67,30 @@ bool_value(const char *name, svn_boolean
}
static svn_error_t *
-entries_dump(const char *dir_path, apr_pool_t *pool)
+entries_dump(const char *dir_path, svn_wc_adm_access_t *related, apr_pool_t *pool)
{
- svn_wc_adm_access_t *adm_access;
+ svn_wc_adm_access_t *adm_access = NULL;
apr_hash_t *entries;
apr_hash_index_t *hi;
svn_boolean_t locked;
svn_error_t *err;
- err = svn_wc_adm_open3(&adm_access, NULL, dir_path, FALSE, 0,
+ err = svn_wc_adm_open3(&adm_access, related, dir_path, FALSE, 0,
NULL, NULL, pool);
if (!err)
{
SVN_ERR(svn_wc_locked(&locked, dir_path, pool));
SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE, pool));
}
+ else if (err && err->apr_err == SVN_ERR_WC_LOCKED
+ && related
+ && ! strcmp(dir_path, svn_wc_adm_access_path(related)))
+ {
+ /* Common caller error: Can't open a baton when there is one. */
+ svn_error_clear(err);
+ SVN_ERR(svn_wc_locked(&locked, dir_path, pool));
+ SVN_ERR(svn_wc_entries_read(&entries, related, TRUE, pool));
+ }
else
{
const char *dir_abspath, *lockfile_path;
@@ -102,12 +112,8 @@ entries_dump(const char *dir_path, apr_p
for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
{
- const void *key;
- void *value;
- const svn_wc_entry_t *entry;
-
- apr_hash_this(hi, &key, NULL, &value);
- entry = value;
+ const char *key = svn__apr_hash_index_key(hi);
+ const svn_wc_entry_t *entry = svn__apr_hash_index_val(hi);
SVN_ERR_ASSERT(strcmp(key, entry->name) == 0);
@@ -168,6 +174,7 @@ struct directory_walk_baton
svn_wc_context_t *wc_ctx;
const char *root_abspath;
const char *prefix_path;
+ svn_wc_adm_access_t *adm_access;
};
/* svn_wc__node_found_func_t implementation for directory_dump */
@@ -252,6 +259,81 @@ directory_dump(const char *path,
return svn_error_trace(svn_wc_context_destroy(bt.wc_ctx));
}
+static svn_error_t *
+tree_dump_dir(const char *local_abspath,
+ svn_node_kind_t kind,
+ void *walk_baton,
+ apr_pool_t *scratch_pool)
+{
+ struct directory_walk_baton *bt = walk_baton;
+ const char *path;
+
+ if (kind != svn_node_dir)
+ return SVN_NO_ERROR;
+
+ /* If LOCAL_ABSPATH a child of or equal to ROOT_ABSPATH, then display
+ a relative path starting with PREFIX_PATH. */
+ path = svn_dirent_skip_ancestor(bt->root_abspath, local_abspath);
+ if (path)
+ path = svn_dirent_join(bt->prefix_path, path, scratch_pool);
+ else
+ path = local_abspath;
+
+ printf("entries = {}\n");
+ SVN_ERR(entries_dump(path, bt->adm_access, scratch_pool));
+
+ printf("dirs['%s'] = entries\n", path);
+ return SVN_NO_ERROR;
+
+}
+
+static svn_error_t *
+tree_dump_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
+{
+ struct directory_walk_baton *bt = baton;
+
+ SVN_ERR(svn_wc__internal_walk_children(bt->wc_ctx->db, bt->root_abspath, FALSE,
+ NULL, tree_dump_dir, bt,
+ svn_depth_infinity,
+ NULL, NULL, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+tree_dump(const char *path,
+ apr_pool_t *scratch_pool)
+{
+ struct directory_walk_baton bt;
+ svn_sqlite__db_t *sdb;
+ svn_wc__db_t *db;
+
+ bt.prefix_path = path;
+
+ /* Obtain an access baton to allow re-using the same wc_db for all access */
+ SVN_ERR(svn_wc_adm_open3(&bt.adm_access, NULL, path, FALSE, 0, NULL, NULL,
+ scratch_pool));
+
+ db = svn_wc__adm_get_db(bt.adm_access);
+
+ SVN_ERR(svn_wc__context_create_with_db(&bt.wc_ctx, NULL, db, scratch_pool));
+
+ SVN_ERR(svn_dirent_get_absolute(&bt.root_abspath, path, scratch_pool));
+
+ /* And now get us a transaction on the database to avoid obtaining and
+ releasing locks all the time */
+ SVN_ERR(svn_wc__db_temp_borrow_sdb(&sdb, bt.wc_ctx->db, bt.root_abspath,
+ scratch_pool));
+
+ SVN_ERR(svn_sqlite__with_lock(sdb, tree_dump_txn, &bt, scratch_pool));
+
+ /* And close everything we've opened */
+ SVN_ERR(svn_wc_context_destroy(bt.wc_ctx));
+ SVN_ERR(svn_wc_adm_close2(bt.adm_access, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
int
main(int argc, const char *argv[])
{
@@ -263,7 +345,7 @@ main(int argc, const char *argv[])
if (argc < 2 || argc > 4)
{
- fprintf(stderr, "USAGE: entries-dump [--entries|--subdirs] DIR_PATH\n");
+ fprintf(stderr, "USAGE: entries-dump [--entries|--subdirs|--tree-dump] DIR_PATH\n");
exit(1);
}
@@ -285,9 +367,11 @@ main(int argc, const char *argv[])
cmd = NULL;
if (!cmd || !strcmp(cmd, "--entries"))
- err = entries_dump(path, pool);
+ err = entries_dump(path, NULL, pool);
else if (!strcmp(cmd, "--subdirs"))
err = directory_dump(path, pool);
+ else if (!strcmp(cmd, "--tree-dump"))
+ err = tree_dump(path, pool);
else
err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
"Invalid command '%s'",
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/externals_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/externals_tests.py Sat Feb 23 01:25:38 2013
@@ -2972,13 +2972,14 @@ 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([
- "\n",
" U " + external_root_path + "\n",
+ "\n",
"Fetching external item into '" + external_ex_path + "':\n",
"A " + external_pi_path + "\n",
"A " + external_rho_path + "\n",
"A " + external_tau_path + "\n",
"Checked out external at revision 2.\n",
+ "\n",
"Checked out revision 2.\n",
"A " + external_root_path + "\n"
])
@@ -3131,9 +3132,9 @@ def pinned_externals(sbox):
repo_X_mu = repo_url + '/X/mu'
- expected_output = verify.RegexOutput([
+ expected_output = verify.RegexOutput(
'^ 1 jrandom .* mu$'
- ])
+ )
svntest.actions.run_and_verify_svn(None, expected_output, [],
'list', repo_X_mu, '-v')
@@ -3187,6 +3188,44 @@ def pinned_externals(sbox):
svntest.actions.verify_disk(wc_dir, expected_disk)
+# Test for issue #3741 'externals not removed when working copy is made shallow'
+@Issue(3741)
+def update_dir_external_shallow(sbox):
+ "shallow update should remove externals"
+
+ sbox.build()
+
+ # Create an external in r2
+ sbox.simple_propset('svn:externals', '^/A/D/H X', 'A/B/E')
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ # Now make A/B/E shallow by updating with "--set-depth empty"
+ expected_output = svntest.wc.State(sbox.wc_dir, {
+ 'A/B/E/alpha' : Item(status='D '),
+ 'A/B/E/X' : Item(verb='Removed external'),
+ 'A/B/E/beta' : Item(status='D '),
+ })
+ svntest.actions.run_and_verify_update(sbox.wc_dir,
+ expected_output, None, None,
+ None, None, None, None, None, False,
+ '--set-depth=empty',
+ sbox.ospath('A/B/E'))
+
+ # And bring the external back by updating with "--set-depth infinity"
+ expected_output = svntest.wc.State(sbox.wc_dir, {
+ 'A/B/E/X/psi' : Item(status='A '),
+ 'A/B/E/X/chi' : Item(status='A '),
+ 'A/B/E/X/omega' : Item(status='A '),
+ 'A/B/E/alpha' : Item(status='A '),
+ 'A/B/E/beta' : Item(status='A '),
+ })
+ svntest.actions.run_and_verify_update(sbox.wc_dir,
+ expected_output, None, None,
+ None, None, None, None, None, False,
+ '--set-depth=infinity',
+ sbox.ospath('A/B/E'))
+
########################################################################
# Run the tests
@@ -3239,6 +3278,7 @@ test_list = [ None,
list_include_externals,
move_with_file_externals,
pinned_externals,
+ update_dir_external_shallow,
]
if __name__ == '__main__':
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/info_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/info_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/info_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/info_tests.py Sat Feb 23 01:25:38 2013
@@ -34,6 +34,8 @@ logger = logging.getLogger()
# Our testing module
import svntest
+from prop_tests import binary_mime_type_on_text_file_warning
+
# (abbreviation)
Skip = svntest.testcase.Skip_deco
SkipUnless = svntest.testcase.SkipUnless_deco
@@ -494,7 +496,9 @@ def binary_tree_conflict(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- sbox.simple_propset('svn:mime-type', 'binary/octet-stream', 'iota')
+ svntest.main.run_svn(binary_mime_type_on_text_file_warning,
+ 'propset', 'svn:mime-type', 'binary/octet-stream',
+ sbox.ospath('iota'))
sbox.simple_commit()
iota = sbox.ospath('iota')
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/input_validation_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/input_validation_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/input_validation_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/input_validation_tests.py Sat Feb 23 01:25:38 2013
@@ -111,15 +111,15 @@ def invalid_delete_targets(sbox):
"invalid targets for 'delete'"
sbox.build(read_only=True)
for (target1, target2) in [("iota", "^/"), ("file://", "iota")]:
- run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot mix repository and working "
+ run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working "
"copy targets", 'delete', target1, target2)
def invalid_diff_targets(sbox):
"invalid targets for 'diff'"
sbox.build(read_only=True)
- for (target1, target2) in [("iota", "^/"), ("file://", "iota")]:
- run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot mix repository and working "
- "copy targets", 'diff', target1, target2)
+ for (target1, target2, target3) in [("iota", "^/", "A/mu"), ("file://", "iota", "A/mu")]:
+ run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working "
+ "copy targets", 'diff', target1, target2, target3)
def invalid_export_targets(sbox):
"invalid targets for 'export'"
@@ -202,14 +202,14 @@ def invalid_lock_targets(sbox):
"wc paths and repo URL target mixture for 'lock'"
sbox.build(read_only=True)
for (target1, target2) in [("iota", "^/"), ("file://", "iota")]:
- run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot mix repository and working "
+ run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working "
"copy targets", 'lock', target1, target2)
def invalid_unlock_targets(sbox):
"wc paths and repo URL target mixture for 'unlock'"
sbox.build(read_only=True)
for (target1, target2) in [("iota", "^/"), ("file://", "iota")]:
- run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot mix repository and working "
+ run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working "
"copy targets", 'unlock', target1, target2)
def invalid_status_targets(sbox):
@@ -243,7 +243,7 @@ def invalid_relocate_targets(sbox):
def invalid_mkdir_targets(sbox):
"invalid targets for 'mkdir'"
sbox.build(read_only=True)
- run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot mix repository and working "
+ run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working "
"copy targets", 'mkdir', "folder", "^/folder")
def invalid_update_targets(sbox):
@@ -252,6 +252,47 @@ def invalid_update_targets(sbox):
run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'update',
"^/")
+def delete_repos_root(sbox):
+ "do stupid things with the repository root"
+
+ sbox.build(read_only=True)
+ wc_dir = sbox.wc_dir
+ repo_url = sbox.repo_url
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+
+ expected_status.tweak('A/D/G', switched='S')
+ expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
+ svntest.actions.run_and_verify_switch(sbox.wc_dir, sbox.ospath('A/D/G'),
+ repo_url,
+ None, None, expected_status,
+ None, None, None, None, None, None,
+ '--set-depth', 'empty', '--ignore-ancestry')
+
+ expected_status.tweak('A/B/F', switched='S')
+ svntest.actions.run_and_verify_switch(sbox.wc_dir, sbox.ospath('A/B/F'),
+ repo_url,
+ None, None, expected_status,
+ None, None, None, None, None, None,
+ '--depth', 'empty', '--ignore-ancestry')
+
+ # Delete the wcroot (which happens to be the repository root)
+ expected_error = 'svn: E155035: \'.*\' is the root of a working copy ' + \
+ 'and cannot be deleted'
+ svntest.actions.run_and_verify_svn('Delete root', [], expected_error,
+ 'rm', wc_dir)
+
+ # This should produce some error, because we can never commit this
+ expected_error = '.*repository root.*'
+ svntest.actions.run_and_verify_svn('Move root', None, expected_error,
+ 'mv', sbox.ospath('A/D/G'),
+ sbox.ospath('Z'))
+
+ # And this currently fails with another nasty error about a wc-lock
+ expected_error = '.*repository root.*'
+ svntest.actions.run_and_verify_svn('Delete root', [], expected_error,
+ 'rm', sbox.ospath('A/B/F'))
+
########################################################################
# Run the tests
@@ -281,6 +322,7 @@ test_list = [ None,
invalid_relocate_targets,
invalid_mkdir_targets,
invalid_update_targets,
+ delete_repos_root,
]
if __name__ == '__main__':
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/lock_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/lock_tests.py Sat Feb 23 01:25:38 2013
@@ -1787,7 +1787,30 @@ def locks_stick_over_switch(sbox):
repo_url + '/A',
expected_output, None, expected_status)
-
+@Issue(4304)
+def lock_unlock_deleted(sbox):
+ "lock/unlock a deleted file"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', sbox.ospath('A/mu'))
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('A/mu', status='D ')
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ expected_output = '\'mu\' locked by user \'jrandom\'.'
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'lock', sbox.ospath('A/mu'))
+ expected_status.tweak('A/mu', writelocked='K')
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ expected_output = '\'mu\' unlocked.'
+ svntest.actions.run_and_verify_svn(None, expected_output, [],
+ 'unlock', sbox.ospath('A/mu'))
+ expected_status.tweak('A/mu', writelocked=None)
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
########################################################################
# Run the tests
@@ -1839,6 +1862,7 @@ test_list = [ None,
lock_invalid_token,
lock_multi_wc,
locks_stick_over_switch,
+ lock_unlock_deleted,
]
if __name__ == '__main__':
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/merge_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/merge_authz_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/merge_authz_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/merge_authz_tests.py Sat Feb 23 01:25:38 2013
@@ -122,7 +122,7 @@ def mergeinfo_and_skipped_paths(sbox):
A_COPY_2_H_path = os.path.join(wc_restricted, "A_COPY_2", "D", "H")
A_COPY_3_path = os.path.join(wc_restricted, "A_COPY_3")
omega_path = os.path.join(wc_restricted, "A_COPY", "D", "H", "omega")
- zeta_path = os.path.join(wc_dir, "A", "D", "H", "zeta")
+ zeta_path = sbox.ospath("A/D/H/zeta")
# Merge r4:8 into the restricted WC's A_COPY.
#
@@ -212,6 +212,8 @@ def mergeinfo_and_skipped_paths(sbox):
# always takes precedence in terms of getting *non*-inheritable mergeinfo.
expected_output = wc.State(A_COPY_2_path, {
'D/H/omega' : Item(status='U '),
+ # Below the skip
+ 'D/G/rho' : Item(status=' ', treeconflict='U'),
})
expected_mergeinfo_output = wc.State(A_COPY_2_path, {
'' : Item(status=' U'),
@@ -257,7 +259,7 @@ def mergeinfo_and_skipped_paths(sbox):
})
expected_skip = wc.State(A_COPY_2_path, {
'B/E' : Item(verb='Skipped missing target'),
- 'D/G/rho' : Item(verb='Skipped'),
+ 'D/G' : Item(verb='Skipped missing target'),
'D/H/psi' : Item(verb='Skipped missing target'),
})
svntest.actions.run_and_verify_merge(A_COPY_2_path, '4', '8',
@@ -501,10 +503,10 @@ def merge_fails_if_subtree_is_deleted_on
svntest.main.wc_author2 + " = rw")})
# Some paths we'll care about
- Acopy_path = os.path.join(wc_dir, 'A_copy')
- gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
- Acopy_gamma_path = os.path.join(wc_dir, 'A_copy', 'D', 'gamma')
- Acopy_D_path = os.path.join(wc_dir, 'A_copy', 'D')
+ Acopy_path = sbox.ospath('A_copy')
+ gamma_path = sbox.ospath('A/D/gamma')
+ Acopy_gamma_path = sbox.ospath('A_copy/D/gamma')
+ Acopy_D_path = sbox.ospath('A_copy/D')
A_url = sbox.repo_url + '/A'
Acopy_url = sbox.repo_url + '/A_copy'
@@ -622,12 +624,12 @@ def reintegrate_fails_if_no_root_access(
# Some paths we'll care about
wc_dir = sbox.wc_dir
- A_path = os.path.join(wc_dir, 'A')
- A_COPY_path = os.path.join(wc_dir, 'A_COPY')
- beta_COPY_path = os.path.join(wc_dir, 'A_COPY', 'B', 'E', 'beta')
- rho_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'G', 'rho')
- omega_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'H', 'omega')
- psi_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'H', 'psi')
+ A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
+ beta_COPY_path = sbox.ospath('A_COPY/B/E/beta')
+ rho_COPY_path = sbox.ospath('A_COPY/D/G/rho')
+ omega_COPY_path = sbox.ospath('A_COPY/D/H/omega')
+ psi_COPY_path = sbox.ospath('A_COPY/D/H/psi')
# Copy A@1 to A_COPY in r2, and then make some changes to A in r3-6.
sbox.build()
@@ -635,7 +637,7 @@ def reintegrate_fails_if_no_root_access(
expected_disk, expected_status = set_up_branch(sbox)
# Make a change on the branch, to A_COPY/mu, commit in r7.
- svntest.main.file_write(os.path.join(wc_dir, "A_COPY", "mu"),
+ svntest.main.file_write(sbox.ospath("A_COPY/mu"),
"Changed on the branch.")
expected_output = wc.State(wc_dir, {'A_COPY/mu' : Item(verb='Sending')})
expected_status.tweak('A_COPY/mu', wc_rev=7)
@@ -735,6 +737,133 @@ def reintegrate_fails_if_no_root_access(
None, True, True,
'--reintegrate', A_path)
+#----------------------------------------------------------------------
+# Test for issue #4319 'faulty merge notifications when target subtree
+# unreadable'.
+@SkipUnless(svntest.main.server_has_mergeinfo)
+@Skip(svntest.main.is_ra_type_file)
+@Issue(4319)
+@XFail()
+def merge_notifications_and_authz_skips(sbox):
+ "merge notifications when target subtree unreadable"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ deep_source_tree = sbox.ospath('A/C/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z')
+ deep_source_file = sbox.ospath('A/C/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/nu')
+ branch_root = sbox.ospath('branch')
+
+ # r2 - branch ^/A to ^/branch
+ sbox.simple_copy('A', 'branch')
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ # r3 - Add a deep subtree
+ svntest.actions.run_and_verify_svn(None, None, [], 'mkdir',
+ deep_source_tree, '--parents')
+ svntest.main.file_write(deep_source_file, "This is the file 'nu'.\n")
+ svntest.actions.run_and_verify_svn(None, None, [], 'add', deep_source_file)
+ sbox.simple_commit()
+
+ #
+ # Create a restrictive authz where part of the merge source and part
+ # of the target are inaccesible.
+ sbox.simple_update(revision=0)
+ write_restrictive_svnserve_conf(sbox.repo_dir)
+ write_authz_file(sbox, {"/" : svntest.main.wc_author +"=rw",
+ # Make a subtree in the merge target inaccessible.
+ "/branch/C" : svntest.main.wc_author + "=",
+ })
+ sbox.simple_update()
+
+ expected_output = wc.State(branch_root, {
+ })
+ expected_mergeinfo_output = wc.State(branch_root, {
+ '' : Item(status=' U'),
+ })
+ expected_elision_output = wc.State(branch_root, {
+ })
+ expected_status = wc.State(branch_root, {
+ '' : Item(status=' M', wc_rev=3),
+ 'D/H/chi' : Item(status=' ', wc_rev=3),
+ 'D/H/omega' : Item(status=' ', wc_rev=3),
+ 'D/H/psi' : Item(status=' ', wc_rev=3),
+ 'D/H' : Item(status=' ', wc_rev=3),
+ 'D/gamma' : Item(status=' ', wc_rev=3),
+ 'D' : Item(status=' ', wc_rev=3),
+ 'D/G' : Item(status=' ', wc_rev=3),
+ 'D/G/pi' : Item(status=' ', wc_rev=3),
+ 'D/G/rho' : Item(status=' ', wc_rev=3),
+ 'D/G/tau' : Item(status=' ', wc_rev=3),
+ 'B/lambda' : Item(status=' ', wc_rev=3),
+ 'B/E' : Item(status=' ', wc_rev=3),
+ 'B/E/alpha' : Item(status=' ', wc_rev=3),
+ 'B/E/beta' : Item(status=' ', wc_rev=3),
+ 'B/F' : Item(status=' ', wc_rev=3),
+ 'B' : Item(status=' ', wc_rev=3),
+ 'mu' : Item(status=' ', wc_rev=3),
+ })
+ expected_disk = wc.State('', {
+ '' : Item(props={SVN_PROP_MERGEINFO : '/A:2-3*'}),
+ 'D/H/omega' : Item("This is the file 'omega'.\n"),
+ 'D/H/chi' : Item("This is the file 'chi'.\n"),
+ 'D/H/psi' : Item("This is the file 'psi'.\n"),
+ 'D/H' : Item(),
+ 'D/gamma' : Item("This is the file 'gamma'.\n"),
+ 'D' : Item(),
+ 'D/G' : Item(),
+ 'D/G/pi' : Item("This is the file 'pi'.\n"),
+ 'D/G/rho' : Item("This is the file 'rho'.\n"),
+ 'D/G/tau' : Item("This is the file 'tau'.\n"),
+ 'B/lambda' : Item("This is the file 'lambda'.\n"),
+ 'B/E' : Item(),
+ 'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+ 'B/E/beta' : Item("This is the file 'beta'.\n"),
+ 'B/F' : Item(),
+ 'B' : Item(),
+ 'mu' : Item("This is the file 'mu'.\n"),
+ })
+ expected_skip = wc.State(branch_root,
+ {'C' : Item(verb='Skipped missing target')})
+ # This fails because notifications for all the added subtrees under
+ # branch/C occur:
+ #
+ # >svn merge ^^/A branch -r1:3
+ # Skipped missing target: 'branch\C'
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z\nu
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V\W
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U\V
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T\U
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S\T
+ # A branch\C\J\K\L\M\N\O\P\Q\R\S
+ # A branch\C\J\K\L\M\N\O\P\Q\R
+ # A branch\C\J\K\L\M\N\O\P\Q
+ # A branch\C\J\K\L\M\N\O\P
+ # A branch\C\J\K\L\M\N\O
+ # A branch\C\J\K\L\M\N
+ # A branch\C\J\K\L\M
+ # A branch\C\J\K\L
+ # A branch\C\J\K
+ # A branch\C\J
+ # --- Recording mergeinfo for merge of r2 through r3 into 'branch':
+ # U branch
+ # Summary of conflicts:
+ # Skipped paths: 1
+ svntest.actions.run_and_verify_merge(branch_root, None, None,
+ sbox.repo_url + '/A', None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, None, None, None,
+ None, 1, 0)
+
########################################################################
# Run the tests
@@ -744,6 +873,7 @@ test_list = [ None,
mergeinfo_and_skipped_paths,
merge_fails_if_subtree_is_deleted_on_src,
reintegrate_fails_if_no_root_access,
+ merge_notifications_and_authz_skips,
]
serial_only = True
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/merge_automatic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/merge_automatic_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/merge_automatic_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/merge_automatic_tests.py Sat Feb 23 01:25:38 2013
@@ -984,6 +984,147 @@ def merge_to_reverse_cherry_subtree_to_m
None, None, None, None,
None, 1, 0, A_COPY_path)
+#----------------------------------------------------------------------
+# Automatic merges should notice ancestory for replaced files
+@SkipUnless(server_has_mergeinfo)
+def merge_replacement(sbox):
+ "notice ancestory for replaced files"
+
+ A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_copy')
+ A_COPY_mu_path = sbox.ospath('A_copy/mu')
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ sbox.simple_copy('A', 'A_copy')
+ # Commit as r2
+ sbox.simple_commit()
+
+ sbox.simple_rm('A_copy/B/lambda')
+ sbox.simple_copy('A_copy/D/gamma', 'A_copy/B/lambda')
+
+ sbox.simple_rm('A_copy/mu')
+ svntest.main.file_write(A_COPY_mu_path, "Branch edit to 'mu'.\n")
+ sbox.simple_add('A_copy/mu')
+
+ # Commit as r3
+ sbox.simple_commit()
+
+ expected_output = wc.State(A_path, {
+ 'B/lambda' : Item(status='R '),
+ 'mu' : Item(status='R '),
+ })
+ expected_mergeinfo_output = wc.State(A_path, {
+ '' : Item(status=' U'),
+ })
+ expected_elision_output = wc.State(A_path, {
+ })
+
+ expected_status = wc.State(A_path, {
+ '' : Item(status=' M', wc_rev='1'),
+ 'B' : Item(status=' ', wc_rev='1'),
+ 'mu' : Item(status='R ', copied='+', wc_rev='-'),
+ 'B/E' : Item(status=' ', wc_rev='1'),
+ 'B/E/alpha' : Item(status=' ', wc_rev='1'),
+ 'B/E/beta' : Item(status=' ', wc_rev='1'),
+ 'B/lambda' : Item(status='R ', copied='+', wc_rev='-'),
+ 'B/F' : Item(status=' ', wc_rev='1'),
+ 'C' : Item(status=' ', wc_rev='1'),
+ 'D' : Item(status=' ', wc_rev='1'),
+ 'D/G' : Item(status=' ', wc_rev='1'),
+ 'D/G/pi' : Item(status=' ', wc_rev='1'),
+ 'D/G/rho' : Item(status=' ', wc_rev='1'),
+ 'D/G/tau' : Item(status=' ', wc_rev='1'),
+ 'D/gamma' : Item(status=' ', wc_rev='1'),
+ 'D/H' : Item(status=' ', wc_rev='1'),
+ 'D/H/chi' : Item(status=' ', wc_rev='1'),
+ 'D/H/psi' : Item(status=' ', wc_rev='1'),
+ 'D/H/omega' : Item(status=' ', wc_rev='1'),
+ })
+
+ expected_disk = wc.State('', {
+ '' : Item(props={SVN_PROP_MERGEINFO : '/A_copy:2-3'}),
+ 'B' : Item(),
+ 'mu' : Item("Branch edit to 'mu'.\n"),
+ 'B/E' : Item(),
+ 'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+ 'B/E/beta' : Item("This is the file 'beta'.\n"),
+ 'B/lambda' : Item("This is the file 'gamma'.\n"),
+ 'B/F' : Item(),
+ 'C' : Item(),
+ 'D' : Item(),
+ 'D/G' : Item(),
+ 'D/G/pi' : Item("This is the file 'pi'.\n"),
+ 'D/G/rho' : Item("This is the file 'rho'.\n"),
+ 'D/G/tau' : Item("This is the file 'tau'.\n"),
+ 'D/gamma' : Item("This is the file 'gamma'.\n"),
+ 'D/H' : Item(),
+ 'D/H/chi' : Item("This is the file 'chi'.\n"),
+ 'D/H/psi' : Item("This is the file 'psi'.\n"),
+ 'D/H/omega' : Item("This is the file 'omega'.\n"),
+ })
+
+ expected_skip = wc.State(A_COPY_path, { })
+
+ svntest.actions.run_and_verify_merge(A_path, None, None,
+ sbox.repo_url + '/A_copy', None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, None, None, None,
+ None, 1, 0, A_path)
+
+@SkipUnless(server_has_mergeinfo)
+@Issue(4313)
+
+# Test for issue #4313 'replaced merges source causes assertion during
+# automatic merge'
+def auto_merge_handles_replacements_in_merge_source(sbox):
+ "automerge handles replacements in merge source"
+
+ sbox.build()
+
+ A_path = sbox.ospath('A')
+ branch1_path = sbox.ospath('branch-1')
+ branch2_path = sbox.ospath('branch-2')
+
+ # r2 - Make two branches.
+ sbox.simple_copy('A', 'branch-1')
+ sbox.simple_copy('A', 'branch-2')
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ # r3 - Replace 'A' with 'branch-1'.
+ svntest.main.run_svn(None, 'del', A_path)
+ svntest.main.run_svn(None, 'copy', branch1_path, A_path)
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ # Merge^/A to branch-2, it should be a no-op but for mergeinfo changes,
+ # but it *should* work. Previously this failed because automatic merges
+ # weren't adhering to the merge source normalization rules, resulting in
+ # this assertion:
+ #
+ # >svn merge ^/A branch-2
+ # ..\..\..\subversion\libsvn_client\merge.c:4568: (apr_err=235000)
+ # svn: E235000: In file '..\..\..\subversion\libsvn_client\merge.c'
+ # line 4568: assertion failed (apr_hash_count(implicit_src_mergeinfo)
+ # == 1)
+ #
+ # This application has requested the Runtime to terminate it in an
+ # unusual way.
+ # Please contact the application's support team for more information.
+ svntest.actions.run_and_verify_svn(
+ None,
+ ["--- Recording mergeinfo for merge of r2 into '" + branch2_path + "':\n",
+ " U " + branch2_path + "\n",
+ "--- Recording mergeinfo for merge of r3 into '" + branch2_path + "':\n",
+ " G " + branch2_path + "\n"],
+ [], 'merge', sbox.repo_url + '/A', branch2_path)
+
########################################################################
# Run the tests
@@ -1009,6 +1150,8 @@ test_list = [ None,
cherry3_fwd,
subtree_to_and_fro,
merge_to_reverse_cherry_subtree_to_merge_to,
+ merge_replacement,
+ auto_merge_handles_replacements_in_merge_source,
]
if __name__ == '__main__':
Modified: subversion/branches/ev2-export/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/ev2-export/subversion/tests/cmdline/merge_reintegrate_tests.py Sat Feb 23 01:25:38 2013
@@ -48,6 +48,62 @@ from merge_tests import set_up_branch
from merge_tests import expected_merge_output
#----------------------------------------------------------------------
+def run_reintegrate(src_url, tgt_path):
+ """Run 'svn merge --reintegrate SRC_URL TGT_PATH'. Raise an error if
+ there is nothing on stdout, anything on stderr, or a non-zero exit
+ code.
+ """
+ svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
+ 'merge', '--reintegrate',
+ src_url, tgt_path)
+
+def run_reintegrate_expect_error(src_url, tgt_path,
+ expected_stdout, expected_stderr):
+ """Run 'svn merge --reintegrate SRC_URL TGT_PATH'. Raise an error
+ unless stdout and stderr both match and the exit code is non-zero.
+ Every line of stderr must match the regex EXPECTED_STDERR.
+ """
+ expected_stderr += "|(.*apr_err.*)" # In case of debug build
+
+ # The actions.run_and_verify_* methods are happy if one line of the error
+ # matches the regex, but we want to check that every line matches.
+ # So we will pass the stderr to svntest.verify.verify_outputs()
+ # ourselves, but as the 'actual_stdout' argument, that way each line of
+ # error must match the regex.
+ exit_code, out, err = svntest.actions.run_and_verify_svn(
+ None, expected_stdout, svntest.verify.AnyOutput,
+ 'merge', '--reintegrate',
+ src_url, tgt_path)
+ assert exit_code
+ svntest.verify.verify_outputs(
+ "Reintegrate failed but not in the way expected",
+ err, None,
+ expected_stderr, None,
+ True) # Match *all* lines
+
+def run_and_verify_reintegrate(tgt_dir, src_url,
+ output_tree,
+ mergeinfo_output_tree,
+ elision_output_tree,
+ disk_tree, status_tree, skip_tree,
+ error_re_string = None,
+ check_props = True,
+ dry_run = True):
+ """Run 'svn merge --reintegrate SRC_URL TGT_DIR'. Raise an error if
+ there is nothing on stdout, anything on stderr, or a non-zero exit
+ code, or if the expected ERROR_RE_STRING or any of the given expected
+ trees don't match.
+ """
+ svntest.actions.run_and_verify_merge(
+ tgt_dir, None, None, src_url, None,
+ output_tree, mergeinfo_output_tree, elision_output_tree,
+ disk_tree, status_tree, skip_tree,
+ error_re_string,
+ None, None, None, None, check_props, dry_run,
+ '--reintegrate', tgt_dir)
+
+
+#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@Issue(3640)
def basic_reintegrate(sbox):
@@ -204,17 +260,15 @@ def basic_reintegrate(sbox):
})
k_expected_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-8'})
expected_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
k_expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_path)
+ None, True, True)
# Test issue #3640:
#
@@ -263,17 +317,15 @@ def basic_reintegrate(sbox):
expected_status.tweak(wc_rev=9)
k_expected_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-9'})
expected_skip = wc.State(A_MOVED_path, {})
- svntest.actions.run_and_verify_merge(A_MOVED_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_MOVED_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_MOVED_path)
+ None, True, True)
#----------------------------------------------------------------------
def reintegrate_with_rename(sbox):
@@ -492,17 +544,15 @@ def reintegrate_with_rename(sbox):
contents="This is the file 'tau'.\n")
})
expected_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
k_expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_path)
+ None, True, True)
# Finally, commit the result of the merge (r10).
expected_output = wc.State(wc_dir, {
@@ -625,17 +675,15 @@ def reintegrate_branch_never_merged_to(s
'D/H/psi' : Item("New content"),
})
expected_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
k_expected_disk,
k_expected_status,
expected_skip,
- None, None, None, None,
- None, True, True,
- '--reintegrate', A_path)
+ None, True, True)
# Finally, commit the result of the merge (r9).
expected_output = wc.State(wc_dir, {
@@ -656,15 +704,22 @@ def reintegrate_fail_on_modified_wc(sbox
sbox.build()
wc_dir = sbox.wc_dir
A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
mu_path = os.path.join(A_path, "mu")
ignored_expected_disk, ignored_expected_status = set_up_branch(sbox)
+
+ # Do a 'sync' merge first so that the following merge really needs to be a
+ # reintegrate, so that an equivalent automatic merge would behave the same.
+ svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path)
+ sbox.simple_commit()
+
svntest.main.file_write(mu_path, "Changed on 'trunk' (the merge target).")
sbox.simple_update() # avoid mixed-revision error
- svntest.actions.run_and_verify_merge(
- A_path, None, None, sbox.repo_url + '/A_COPY', None, None, None, None,
+ run_and_verify_reintegrate(
+ A_path, sbox.repo_url + '/A_COPY', None, None, None,
None, None, None,
".*Cannot merge into a working copy that has local modifications.*",
- None, None, None, None, True, False, '--reintegrate', A_path)
+ True, False)
#----------------------------------------------------------------------
def reintegrate_fail_on_mixed_rev_wc(sbox):
@@ -683,11 +738,11 @@ def reintegrate_fail_on_mixed_rev_wc(sbo
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
expected_status, None, wc_dir)
# Try merging into that same wc, expecting failure.
- svntest.actions.run_and_verify_merge(
- A_path, None, None, sbox.repo_url + '/A_COPY', None, None, None, None,
+ run_and_verify_reintegrate(
+ A_path, sbox.repo_url + '/A_COPY', None, None, None,
None, None, None,
".*Cannot merge into mixed-revision working copy.*",
- None, None, None, None, True, False, '--reintegrate', A_path)
+ True, False)
#----------------------------------------------------------------------
def reintegrate_fail_on_switched_wc(sbox):
@@ -695,10 +750,29 @@ def reintegrate_fail_on_switched_wc(sbox
sbox.build()
wc_dir = sbox.wc_dir
A_path = sbox.ospath('A')
+ A_COPY_path = sbox.ospath('A_COPY')
G_path = os.path.join(A_path, "D", "G")
switch_url = sbox.repo_url + "/A/D/H"
expected_disk, expected_status = set_up_branch(sbox)
+ # Do a 'sync' merge first so that the following merge really needs to be a
+ # reintegrate, so that an equivalent automatic merge would behave the same.
+ expected_disk.tweak(
+ 'A_COPY/D/H/psi',
+ 'A_COPY/D/G/rho',
+ 'A_COPY/B/E/beta',
+ 'A_COPY/D/H/omega',
+ contents="New content")
+ expected_status.tweak(
+ 'A_COPY/D/H/psi',
+ 'A_COPY/D/G/rho',
+ 'A_COPY/B/E/beta',
+ 'A_COPY/D/H/omega',
+ 'A_COPY',
+ wc_rev=7)
+ svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', A_COPY_path)
+ sbox.simple_commit()
+
# Switch a subdir of the target.
expected_output = svntest.wc.State(wc_dir, {
'A/D/G/pi' : Item(status='D '),
@@ -716,10 +790,10 @@ def reintegrate_fail_on_switched_wc(sbox
})
expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
expected_status.add({
- 'A/D/G' : Item(status=' ', wc_rev=6, switched='S'),
- 'A/D/G/chi' : Item(status=' ', wc_rev=6),
- 'A/D/G/psi' : Item(status=' ', wc_rev=6),
- 'A/D/G/omega' : Item(status=' ', wc_rev=6),
+ 'A/D/G' : Item(status=' ', wc_rev=7, switched='S'),
+ 'A/D/G/chi' : Item(status=' ', wc_rev=7),
+ 'A/D/G/psi' : Item(status=' ', wc_rev=7),
+ 'A/D/G/omega' : Item(status=' ', wc_rev=7),
})
svntest.actions.run_and_verify_switch(wc_dir,
G_path,
@@ -730,11 +804,11 @@ def reintegrate_fail_on_switched_wc(sbox
None, None, None, None, None,
False, '--ignore-ancestry')
sbox.simple_update() # avoid mixed-revision error
- svntest.actions.run_and_verify_merge(
- A_path, None, None, sbox.repo_url + '/A_COPY', None, None, None, None,
+ run_and_verify_reintegrate(
+ A_path, sbox.repo_url + '/A_COPY', None, None, None,
None, None, None,
".*Cannot merge into a working copy with a switched subtree.*",
- None, None, None, None, True, False, '--reintegrate', A_path)
+ True, False)
#----------------------------------------------------------------------
# Test for issue #3603 'allow reintegrate merges into WCs with
@@ -804,16 +878,15 @@ def reintegrate_on_shallow_wc(sbox):
'D' : Item(), # Don't expect anything under D, its depth is empty!
})
expected_A_skip = wc.State(A_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
# Now revert the reintegrate and make a second change on the
# branch in r4, but this time change a subtree that corresponds
@@ -832,22 +905,25 @@ def reintegrate_on_shallow_wc(sbox):
expected_A_disk.tweak('D', props={SVN_PROP_MERGEINFO : '/A_COPY/D:2-4*'})
# ... a depth-restricted item is skipped ...
expected_A_skip.add({
- 'D/H/psi' : Item(verb='Skipped')
+ 'D/H' : Item(verb='Skipped missing target')
+ })
+ expected_output.add({
+ # Below the skip
+ 'D/H/psi' : Item(status=' ', treeconflict='U'),
})
# Currently this fails due to r1424469. For a full explanation see
# http://svn.haxx.se/dev/archive-2012-12/0472.shtml
# and http://svn.haxx.se/dev/archive-2012-12/0475.shtml
expected_A_disk.tweak('', props={SVN_PROP_MERGEINFO : '/A_COPY:2-4'})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -916,16 +992,15 @@ def reintegrate_fail_on_stale_source(sbo
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_path, { })
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- [], None, None, None, None, True, True,
- '--reintegrate', A_path)
+ [], True, True)
#----------------------------------------------------------------------
def merge_file_with_space_in_its_path(sbox):
@@ -955,9 +1030,7 @@ def merge_file_with_space_in_its_path(sb
"ci", "-m", "r4", wc_dir)
target_url = sbox.repo_url + '/some%20dir/file2'
- svntest.actions.run_and_verify_svn(None, None, [],
- "merge", "--reintegrate", target_url,
- file1)
+ run_reintegrate(target_url, file1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -1175,16 +1248,15 @@ def reintegrate_with_subtree_mergeinfo(s
'D/H/omega' : Item("New content"),
})
expected_A_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
# Make some more changes to A_COPY so that the same revisions have *not*
# been uniformly applied from A to A_COPY. In this case the reintegrate
@@ -1224,19 +1296,10 @@ def reintegrate_with_subtree_mergeinfo(s
# to it from A, the merge should fail. Further we expect an error message
# that highlights the fact that A_COPY/D is the offending subtree.
#
- # The actions.run_and_verify_* methods are happy if one line of the error
- # matches the regex, but we want to know that the error actually provides
- # specific information about the paths that are stopping --reintegrate from
- # working. So we will pass the stderr to svntest.verify.verify_outputs()
- # ourselves, but as the 'actual_stdout' argument, that way each line of
- # error must match the regex.
- exit_code, out, err = svntest.actions.run_and_verify_svn(
- None, [], svntest.verify.AnyOutput,
- 'merge', '--reintegrate', sbox.repo_url + '/A_COPY', A_path)
-
- svntest.verify.verify_outputs("Reintegrate failed but not "
- "in the way expected",
- err, None,
+ # We want to know that the error provides specific information about the
+ # paths that are stopping --reintegrate from working.
+ run_reintegrate_expect_error(sbox.repo_url + '/A_COPY', A_path,
+ [],
"(svn: E195016: Reintegrate can only be used if "
"revisions 2 through 15 were previously "
"merged from .*/A to the reintegrate source, "
@@ -1245,10 +1308,7 @@ def reintegrate_with_subtree_mergeinfo(s
"|( Missing ranges: /A/D:8\n)"
"|( A_COPY/mu\n)"
"|( Missing ranges: /A/mu:2-12\n)"
- "|(\n)"
- "|(.*apr_err.*)", # In case of debug build
- None,
- True) # Match *all* lines of stdout
+ "|(\n)")
# Test another common situation that can break reintegrate as a result
# of copies and moves:
@@ -1295,6 +1355,14 @@ def reintegrate_with_subtree_mergeinfo(s
expected_status.remove('A/D/gamma')
expected_status.add({'A/D/gamma_moved' : Item(status=' ', wc_rev=16)})
+ # Why is gamma_moved notified as ' G' rather than ' U'? It was
+ # added by the merge and there is only a single editor drive, so
+ # how can any prop changes be merged to it? The answer is that
+ # the merge code does some quiet housekeeping, merging gamma_moved's
+ # inherited mergeinfo into its incoming mergeinfo, see
+ # http://subversion.tigris.org/issues/show_bug.cgi?id=4309
+ # This test is not covering issue #4309 so we let the current
+ # behavior pass.
# r17 - B) Synch merge from A to A_COPY
svntest.actions.run_and_verify_svn(
None,
@@ -1304,7 +1372,7 @@ def reintegrate_with_subtree_mergeinfo(s
'D ' + gamma_COPY_path + '\n',
' U ' + A_COPY_path + '\n',
' U ' + D_COPY_path + '\n',
- ' U ' + gamma_moved_COPY_path + '\n']),
+ ' G ' + gamma_moved_COPY_path + '\n']),
[], 'merge', sbox.repo_url + '/A', A_COPY_path)
expected_output = wc.State(
wc_dir,
@@ -1374,7 +1442,7 @@ def reintegrate_with_subtree_mergeinfo(s
'' : Item(status=' U'),
'mu' : Item(status=' G'),
'D' : Item(status=' U'),
- 'D/gamma_moved' : Item(status=' U'),
+ 'D/gamma_moved' : Item(status=' G'), # More issue #4309 (see above)
})
expected_elision_output = wc.State(A_path, {
})
@@ -1418,26 +1486,49 @@ def reintegrate_with_subtree_mergeinfo(s
'D/G/pi' : Item("This is the file 'pi'.\n"),
'D/G/rho' : Item("New content"),
'D/G/tau' : Item("This is the file 'tau'.\n"),
+ # What's with all this mergeinfo?
+ #
+ # '/A/D/gamma_moved:2-7,9-12' - Incoming from the merge source. Yes,
+ # this mergeinfo describes non-existent path-revs, this is the effect
+ # of issue #3669 'inheritance can result in mergeinfo describing
+ # nonexistent sources', but there is already a test for that issue so
+ # we tolerate it here.
+ #
+ # '/A_COPY/D/gamma_moved:17-19' - Describes the merge performed.
+ #
+ # '/A_COPY_3/D/gamma:9' - Explicit prior to the merge.
+ #
+ #'/A_COPY_3/D/gamma_moved:9' - Incoming from the merge source.
+ # For the curious, this was originally created in r17 when we merged
+ # ^/A to A_COPY. This merge added A_COPY/D/gamma_moved, which had
+ # explicit mergeinfo and due to issue #4309 'wrong notification and
+ # bogus mergeinfo during merge which adds subtree with mergeinfo'
+ # this file inherited this bogus mergeinfo from A_COPY/D. Yes, this
+ # 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.
'D/gamma_moved' : Item(
"Even newer content", props={SVN_PROP_MERGEINFO :
+ '/A/D/gamma_moved:2-7,9-12\n'
'/A_COPY/D/gamma_moved:17-19\n'
- '/A_COPY_3/D/gamma:9'}),
+ '/A_COPY_3/D/gamma:9\n'
+ '/A_COPY_3/D/gamma_moved:9'}),
'D/H' : Item(),
'D/H/chi' : Item("This is the file 'chi'.\n"),
'D/H/psi' : Item("New content"),
'D/H/omega' : Item("New content"),
})
expected_A_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -1494,9 +1585,7 @@ def multiple_reintegrates_from_the_same_
# r11 - Reintegrate the feature branch back to 'A'.
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- svntest.actions.run_and_verify_svn(None, None, [], 'merge', '--reintegrate',
- sbox.repo_url + '/A_FEATURE_BRANCH',
- A_path)
+ run_reintegrate(sbox.repo_url + '/A_FEATURE_BRANCH', A_path)
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
"Reintegrate feature branch back to 'A'",
wc_dir)
@@ -1588,17 +1677,15 @@ def multiple_reintegrates_from_the_same_
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_path, { })
- svntest.actions.run_and_verify_merge(A_path, None, None,
+ run_and_verify_reintegrate(A_path,
sbox.repo_url + '/A_FEATURE_BRANCH',
- None,
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, 1, 1, '--reintegrate', A_path)
+ None, 1, 1)
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
"2nd Reintegrate feature branch back to 'A'",
wc_dir)
@@ -1746,16 +1833,15 @@ def reintegrate_with_self_referential_me
# ..\..\..\subversion\libsvn_fs_fs\tree.c:2886: (apr_err=160013)
# ..\..\..\subversion\libsvn_fs_fs\tree.c:669: (apr_err=160013)
# svn: File not found: revision 4, path '/A2'
- svntest.actions.run_and_verify_merge(A2_path, None, None,
- sbox.repo_url + '/A2.1', None,
+ run_and_verify_reintegrate(A2_path,
+ sbox.repo_url + '/A2.1',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, 1, 0, '--reintegrate', A2_path)
+ None, 1, 0)
#----------------------------------------------------------------------
# Test for issue #3577 '1.7 subtree mergeinfo recording breaks reintegrate'.
@@ -1878,16 +1964,15 @@ def reintegrate_with_subtree_merges(sbox
'D/H/omega' : Item("New content"),
})
expected_A_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_A_disk,
expected_A_status,
expected_A_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
#----------------------------------------------------------------------
# Test for issue #3654 'added subtrees with mergeinfo break reintegrate'.
@@ -1961,9 +2046,7 @@ def added_subtrees_with_mergeinfo_break_
# r14 - Reintegrate A_COPY to A.
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
- svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
- 'merge', '--reintegrate',
- sbox.repo_url + '/A_COPY', A_path)
+ run_reintegrate(sbox.repo_url + '/A_COPY', A_path)
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
'Reintegrate A_COPY to A.',
wc_dir)
@@ -2073,16 +2156,15 @@ def added_subtrees_with_mergeinfo_break_
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- None, None, None, None,
- None, 1, 1, "--reintegrate", A_path)
+ None, 1, 1)
#----------------------------------------------------------------------
# Test for issue #3648 '2-URL merges incorrectly reverse-merge mergeinfo
@@ -2322,14 +2404,14 @@ def reintegrate_creates_bogus_mergeinfo(
})
expected_skip = wc.State(A_COPY_path, {})
- svntest.actions.run_and_verify_merge(A_path, None, None,
- A_COPY_url, None,
+ run_and_verify_reintegrate(A_path,
+ A_COPY_url,
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk, None, expected_skip,
- None, None, None, None, None,
- 1, 1, "--reintegrate", A_path)
+ None,
+ 1, 1)
#----------------------------------------------------------------------
@@ -2391,8 +2473,7 @@ def no_source_subtree_mergeinfo(sbox):
svntest.main.run_svn(None, 'update', wc_dir)
# Reintegrate branch-1 subtree to trunk subtree
- svntest.main.run_svn(None, 'merge', '--reintegrate',
- '^/A/B1/E', sbox.ospath('A/B/E'))
+ run_reintegrate('^/A/B1/E', sbox.ospath('A/B/E'))
svntest.main.run_svn(None, 'commit', '-m', 'log message', wc_dir)
svntest.main.run_svn(None, 'update', wc_dir)
@@ -2446,22 +2527,13 @@ def no_source_subtree_mergeinfo(sbox):
})
expected_skip = wc.State(sbox.ospath('A/B'), {
})
- svntest.actions.run_and_verify_merge(sbox.ospath('A/B'),
- None, None, '^/A/B2', None,
+ run_and_verify_reintegrate(sbox.ospath('A/B'),
+ '^/A/B2',
expected_output, expected_mergeinfo,
expected_elision, expected_disk,
None, expected_skip,
- None, None, None, None, None,
- 1, 1, '--reintegrate',
- sbox.ospath('A/B'))
- # For 1.6 testsuite use:
- # svntest.actions.run_and_verify_merge(sbox.ospath('A/B'),
- # None, None, '^/A/B2',
- # expected_output,
- # expected_disk,
- # None, expected_skip,
- # None, None, None, None, None,
- # 1, 1, '--reintegrate')
+ None,
+ 1, 1)
#----------------------------------------------------------------------
@SkipUnless(server_has_mergeinfo)
@@ -2578,16 +2650,15 @@ def reintegrate_replaced_source(sbox):
'D/H/omega' : Item("New content"),
})
expected_skip = wc.State(A_path, { })
- svntest.actions.run_and_verify_merge(A_path, None, None,
- sbox.repo_url + '/A_COPY', None,
+ run_and_verify_reintegrate(A_path,
+ sbox.repo_url + '/A_COPY',
expected_output,
expected_mergeinfo_output,
expected_elision_output,
expected_disk,
expected_status,
expected_skip,
- [], None, None, None, None, True, True,
- '--reintegrate', A_path)
+ [], True, True)
#----------------------------------------------------------------------
@SkipUnless(svntest.main.is_posix_os)
@@ -2624,8 +2695,7 @@ def reintegrate_symlink_deletion(sbox):
## reintegrate
# ### TODO: verify something here
- svntest.main.run_svn(None, 'merge', '--reintegrate',
- A_COPY_url, A_path)
+ run_reintegrate(A_COPY_url, A_path)
#----------------------------------------------------------------------
def no_op_reintegrate(sbox):
@@ -2645,8 +2715,7 @@ def no_op_reintegrate(sbox):
# Reintegrate; there are no relevant changes on the branch.
# ### TODO: Check the result more carefully than merely that it completed.
- svntest.main.run_svn(None, 'merge', '--reintegrate',
- sbox.repo_url + '/A_COPY', A_path)
+ run_reintegrate(sbox.repo_url + '/A_COPY', A_path)
#----------------------------------------------------------------------
def renamed_branch_reintegrate(sbox):
@@ -2685,8 +2754,7 @@ def renamed_branch_reintegrate(sbox):
# Reintegrate; there are no relevant changes on the branch.
# ### TODO: Check the result more carefully than merely that it completed.
- svntest.main.run_svn(None, 'merge', '--reintegrate',
- sbox.repo_url + '/RENAMED@8', A_path)
+ run_reintegrate(sbox.repo_url + '/RENAMED@8', A_path)
########################################################################
# Run the tests