55
55
# Each test must return on success or raise on failure.
58
#----------------------------------------------------------------------
60
# Helper for update_binary_file() test -- a custom singleton handler.
61
def detect_extra_files(node, extra_files):
62
"""NODE has been discovered as an extra file on disk. Verify that
63
it matches one of the regular expressions in the EXTRA_FILES list of
64
lists, and that its contents matches the second part of the list
65
item. If it matches, remove the match from the list. If it doesn't
66
match, raise an exception."""
68
# Baton is of the form:
70
# [ [wc_dir, pattern, contents],
71
# [wc_dir, pattern, contents], ... ]
73
for fdata in extra_files:
79
match_obj = re.match(pattern, node.name)
84
# Strip the root_node_name from node path
85
# (svntest.tree.root_node_name, currently `__SVN_ROOT_NODE'),
86
# since it doesn't really exist. Also strip the trailing "slash".
88
if real_path.startswith(svntest.tree.root_node_name):
89
real_path = real_path[len(svntest.tree.root_node_name) +
91
real_path = os.path.join(wc_dir, real_path)
93
real_contents = open(real_path).read()
94
if real_contents == contents:
95
extra_files.pop(extra_files.index(fdata)) # delete pattern from list
98
logger.warn("Found unexpected object: %s", node.name)
99
raise svntest.tree.SVNTreeUnequal
103
59
def update_binary_file(sbox):
104
60
"update a locally-modified binary file"
728
662
alpha_path = sbox.ospath('A/B/E/alpha')
729
svntest.actions.run_and_verify_svn("Deleting alpha failed", None, [],
663
svntest.actions.run_and_verify_svn(None, [],
730
664
'rm', alpha_path)
732
666
# Delete a directory containing files
733
667
G_path = sbox.ospath('A/D/G')
734
svntest.actions.run_and_verify_svn("Deleting G failed", None, [],
668
svntest.actions.run_and_verify_svn(None, [],
738
svntest.actions.run_and_verify_svn("Committing deletes failed", None, [],
672
svntest.actions.run_and_verify_svn(None, [],
739
673
'ci', '-m', 'log msg', wc_dir)
741
675
### Update before backdating to avoid obstructed update error for G
742
svntest.actions.run_and_verify_svn("Updating after commit failed", None, [],
676
svntest.actions.run_and_verify_svn(None, [],
745
679
# Backdate to restore deleted items
746
svntest.actions.run_and_verify_svn("Backdating failed", None, [],
680
svntest.actions.run_and_verify_svn(None, [],
747
681
'up', '-r', '1', wc_dir)
749
683
# Modify the file to be deleted, and a file in the directory to be deleted
1961
1884
url2 = sbox.repo_url + '/A2/mu'
1963
1886
# Remember the original text of the file
1964
exit_code, text_r1, err = svntest.actions.run_and_verify_svn(None, None, [],
1887
exit_code, text_r1, err = svntest.actions.run_and_verify_svn(None, [],
1968
1891
# Commit a different version of the file
1969
1892
svntest.main.file_write(file, "Second revision of 'mu'\n")
1970
svntest.actions.run_and_verify_svn(None, None, [],
1893
svntest.actions.run_and_verify_svn(None, [],
1971
1894
'ci', '-m', '', wc_dir)
1973
1896
# Copy an old revision of its directory into a new path in the WC
1974
svntest.actions.run_and_verify_svn(None, None, [],
1897
svntest.actions.run_and_verify_svn(None, [],
1975
1898
'cp', '-r1', dir, dir2)
1977
1900
# Update. (Should do nothing, but added a bogus "revision" in "entries".)
1978
svntest.actions.run_and_verify_svn(None, None, [],
1901
svntest.actions.run_and_verify_svn(None, [],
1981
1904
# Commit, and check that it says it's committing the right thing
1982
1905
exp_out = ['Adding ' + dir2 + '\n',
1906
'Committing transaction...\n',
1984
1907
'Committed revision 3.\n']
1985
svntest.actions.run_and_verify_svn(None, exp_out, [],
1908
svntest.actions.run_and_verify_svn(exp_out, [],
1986
1909
'ci', '-m', '', wc_dir)
1988
1911
# Verify the committed file's content
1989
svntest.actions.run_and_verify_svn(None, text_r1, [],
1912
svntest.actions.run_and_verify_svn(text_r1, [],
1992
1915
#----------------------------------------------------------------------
3931
3832
expected_output,
3933
3834
expected_status,
3935
svntest.tree.detect_conflict_files,
3938
# Test for a wc corruption race condition (possibly introduced in
3939
# r863416) which is easy to trigger if interactive conflict resolution
3940
# dies in the middle of prompting. Specifically, we run an update
3941
# with interactive-conflicts on but close stdin immediately, so the
3942
# prompt errors out; then the dir_baton pool cleanup handlers in the
3943
# WC update editor flush and run incomplete logs and lead to WC
3944
# corruption, detectable by another update command.
3946
# FIXME: With issue #4280 fixed and this test using --force-interactive,
3947
# the test driver can no longer redirect terminal input to cause
3948
# an EOF. Consequently, skip this test so that it does not hang
3951
def eof_in_interactive_conflict_resolver(sbox):
3952
"eof in interactive resolution can't break wc"
3955
wc_dir = sbox.wc_dir
3957
# Set up a custom config directory which *doesn't* turn off
3958
# interactive resolution
3959
config_contents = '''\
3964
interactive-conflicts = true
3966
tmp_dir = os.path.abspath(svntest.main.temp_dir)
3967
config_dir = os.path.join(tmp_dir, 'interactive-conflicts-config')
3968
svntest.main.create_config_dir(config_dir, config_contents)
3970
iota_path = sbox.ospath('iota')
3972
# Modify iota and commit for r2.
3973
svntest.main.file_append(iota_path, "Appended text in r2.\n")
3974
expected_output = svntest.wc.State(wc_dir, {
3975
'iota': Item(verb="Sending"),
3977
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
3978
expected_status.tweak('iota', wc_rev=2)
3979
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
3980
expected_status, None, wc_dir)
3982
# Go back to revision 1.
3983
expected_output = svntest.wc.State(wc_dir, {
3984
'iota' : Item(status='U '),
3987
expected_disk = svntest.main.greek_state.copy()
3989
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
3991
svntest.actions.run_and_verify_update(wc_dir,
4000
# Modify iota differently and try to update *with the interactive
4001
# resolver*. ### The parser won't go so well with the output
4002
svntest.main.file_append(iota_path, "Local mods to r1 text.\n")
4003
svntest.actions.run_and_verify_update(
4004
wc_dir, None, None, None,
4005
"End of file while reading from terminal",
4006
None, None, None, None, 1,
4007
wc_dir, '--force-interactive', '--config-dir', config_dir)
4009
# Now update -r1 again. Hopefully we don't get a checksum error!
4010
expected_output = svntest.wc.State(wc_dir, {
4011
'iota': Item(verb="Skipped"),
4014
# The interactive callback aborts, so the file remains in conflict.
4015
expected_disk.tweak('iota', contents="This is the file 'iota'.\n"
4017
"Local mods to r1 text.\n"
4019
"Appended text in r2.\n"
4022
'iota.r1' : Item(contents="This is the file 'iota'.\n"),
4023
'iota.r2' : Item(contents="This is the file 'iota'.\n"
4024
"Appended text in r2.\n"),
4025
'iota.mine' : Item(contents="This is the file 'iota'.\n"
4026
"Local mods to r1 text.\n"),
4029
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
4030
expected_status.tweak('iota', status='C ', wc_rev=2)
4032
svntest.actions.run_and_verify_update(wc_dir,
3835
extra_files=extra_files)
4042
3838
#----------------------------------------------------------------------
4424
4220
expected_info = {
4426
4222
'Tree conflict' :
4427
'^local file edit, incoming file delete upon update'
4223
'^local file edit, incoming file delete or move upon update'
4428
4224
+ ' Source left: .file.*/F/alpha@2'
4429
4225
+ ' Source right: .none.*(/F/alpha@3)?$',
4432
4228
'Tree conflict' :
4433
'^local dir edit, incoming dir delete upon update'
4229
'^local dir edit, incoming dir delete or move upon update'
4434
4230
+ ' Source left: .dir.*/DF/D1@2'
4435
4231
+ ' Source right: .none.*(/DF/D1@3)?$',
4438
4234
'Tree conflict' :
4439
'^local dir edit, incoming dir delete upon update'
4235
'^local dir edit, incoming dir delete or move upon update'
4440
4236
+ ' Source left: .dir.*/DDF/D1@2'
4441
4237
+ ' Source right: .none.*(/DDF/D1@3)?$',
4444
4240
'Tree conflict' :
4445
'^local dir edit, incoming dir delete upon update'
4241
'^local dir edit, incoming dir delete or move upon update'
4446
4242
+ ' Source left: .dir.*/D/D1@2'
4447
4243
+ ' Source right: .none.*(/D/D1@3)?$',
4450
4246
'Tree conflict' :
4451
'^local dir edit, incoming dir delete upon update'
4247
'^local dir edit, incoming dir delete or move upon update'
4452
4248
+ ' Source left: .dir.*/DD/D1@2'
4453
4249
+ ' Source right: .none.*(/DD/D1@3)?$',
4456
4252
'Tree conflict' :
4457
'^local dir edit, incoming dir delete upon update'
4253
'^local dir edit, incoming dir delete or move upon update'
4458
4254
+ ' Source left: .dir.*/DDD/D1@2'
4459
4255
+ ' Source right: .none.*(/DDD/D1@3)?$',
4504
4307
# Expect the incoming tree deletes and the local leaf deletes to mean
4505
4308
# that all deleted paths are *really* gone, not simply scheduled for
4507
expected_status.tweak('F/alpha',
4513
status='! ', wc_rev=None)
4514
# Remove from expected status and disk everything below the deleted paths.
4515
expected_status.remove('DD/D1/D2',
4522
expected_disk.remove('D/D1',
4310
expected_status.tweak('DD/D1', 'DF/D1', 'DDF/D1', 'DDD/D1',
4311
status='A ', copied='+', treeconflict='C',
4313
expected_status.tweak('DDF/D1/D2', 'DDD/D1/D2',
4314
copied='+', wc_rev='-')
4315
expected_status.tweak('DD/D1/D2', 'DF/D1/beta', 'DDD/D1/D2/D3',
4317
status='D ', copied='+', wc_rev='-')
4318
expected_status.tweak('F/alpha', 'D/D1',
4319
status='! ', treeconflict='C', wc_rev=None)
4532
4321
expected_info = {
4534
4323
'Tree conflict' :
4535
'^local file delete, incoming file delete upon update'
4324
'^local file delete, incoming file delete or move upon update'
4536
4325
+ ' Source left: .file.*/F/alpha@2'
4537
4326
+ ' Source right: .none.*(/F/alpha@3)?$',
4540
4329
'Tree conflict' :
4541
'^local dir delete, incoming dir delete upon update'
4330
'^local dir edit, incoming dir delete or move upon update'
4542
4331
+ ' Source left: .dir.*/DF/D1@2'
4543
4332
+ ' Source right: .none.*(/DF/D1@3)?$',
4546
4335
'Tree conflict' :
4547
'^local dir delete, incoming dir delete upon update'
4336
'^local dir edit, incoming dir delete or move upon update'
4548
4337
+ ' Source left: .dir.*/DDF/D1@2'
4549
4338
+ ' Source right: .none.*(/DDF/D1@3)?$',
4552
4341
'Tree conflict' :
4553
'^local dir delete, incoming dir delete upon update'
4342
'^local dir delete, incoming dir delete or move upon update'
4554
4343
+ ' Source left: .dir.*/D/D1@2'
4555
4344
+ ' Source right: .none.*(/D/D1@3)?$',
4558
4347
'Tree conflict' :
4559
'^local dir delete, incoming dir delete upon update'
4348
'^local dir edit, incoming dir delete or move upon update'
4560
4349
+ ' Source left: .dir.*/DD/D1@2'
4561
4350
+ ' Source right: .none.*(/DD/D1@3)?$',
4564
4353
'Tree conflict' :
4565
'^local dir delete, incoming dir delete upon update'
4354
'^local dir edit, incoming dir delete or move upon update'
4566
4355
+ ' Source left: .dir.*/DDD/D1@2'
4567
4356
+ ' Source right: .none.*(/DDD/D1@3)?$',
4682
4477
'DDF/D1/D2/gamma',)
4684
expected_disk.remove('D/D1',
4694
4479
expected_info = {
4696
4481
'Tree conflict' :
4697
'^local file delete, incoming file delete upon update'
4482
'^local file delete, incoming file delete or move upon update'
4698
4483
+ ' Source left: .file.*/F/alpha@2'
4699
4484
+ ' Source right: .none.*(/F/alpha@3)?$',
4702
4487
'Tree conflict' :
4703
'^local dir delete, incoming dir delete upon update'
4488
'^local dir delete, incoming dir delete or move upon update'
4704
4489
+ ' Source left: .dir.*/DF/D1@2'
4705
4490
+ ' Source right: .none.*(/DF/D1@3)?$',
4708
4493
'Tree conflict' :
4709
'^local dir delete, incoming dir delete upon update'
4494
'^local dir delete, incoming dir delete or move upon update'
4710
4495
+ ' Source left: .dir.*/DDF/D1@2'
4711
4496
+ ' Source right: .none.*(/DDF/D1@3)?$',
4714
4499
'Tree conflict' :
4715
'^local dir delete, incoming dir delete upon update'
4500
'^local dir delete, incoming dir delete or move upon update'
4716
4501
+ ' Source left: .dir.*/D/D1@2'
4717
4502
+ ' Source right: .none.*(/D/D1@3)?$',
4720
4505
'Tree conflict' :
4721
'^local dir delete, incoming dir delete upon update'
4506
'^local dir delete, incoming dir delete or move upon update'
4722
4507
+ ' Source left: .dir.*/DD/D1@2'
4723
4508
+ ' Source right: .none.*(/DD/D1@3)?$',
4726
4511
'Tree conflict' :
4727
'^local dir delete, incoming dir delete upon update'
4512
'^local dir delete, incoming dir delete or move upon update'
4728
4513
+ ' Source left: .dir.*/DDD/D1@2'
4729
4514
+ ' Source right: .none.*(/DDD/D1@3)?$',
4773
4558
def modify_dir(dir):
4774
4559
"""Make some set of local modifications to an existing tree:
4775
4560
A prop change, add a child, delete a child, change a child."""
4776
run_and_verify_svn(None, AnyOutput, [], 'propset', 'p', 'v', dir)
4561
run_and_verify_svn(AnyOutput, [], 'propset', 'p', 'v', dir)
4778
4563
path = os.path.join(dir, 'new_file')
4779
4564
svntest.main.file_write(path, "This is the file 'new_file'.\n")
4780
svntest.actions.run_and_verify_svn(None, None, [], 'add', path)
4565
svntest.actions.run_and_verify_svn(None, [], 'add', path)
4782
4567
path = os.path.join(dir, 'C', 'N')
4784
4569
path2 = os.path.join(dir, 'C', 'N', 'nu')
4785
4570
svntest.main.file_write(path2, "This is the file 'nu'.\n")
4786
svntest.actions.run_and_verify_svn(None, None, [], 'add', path)
4571
svntest.actions.run_and_verify_svn(None, [], 'add', path)
4788
4573
path = os.path.join(dir, 'B', 'lambda')
4789
svntest.actions.run_and_verify_svn(None, None, [], 'delete', path)
4574
svntest.actions.run_and_verify_svn(None, [], 'delete', path)
4791
4576
path = os.path.join(dir, 'B', 'E', 'alpha')
4792
4577
svntest.main.file_append(path, "An extra line.\n")
4794
4579
# Prep for both scenarios
4796
run_and_verify_svn(None, AnyOutput, [], 'ci', A, '-m', 'modify_dir')
4797
run_and_verify_svn(None, AnyOutput, [], 'up', wc_dir)
4581
run_and_verify_svn(AnyOutput, [], 'ci', A, '-m', 'modify_dir')
4582
run_and_verify_svn(AnyOutput, [], 'up', wc_dir)
4799
4584
# Existing scenario
4800
4585
wc2 = sbox.add_wc_path('wc2')
4801
4586
A2 = os.path.join(wc2, 'A')
4802
4587
svntest.actions.duplicate_dir(sbox.wc_dir, wc2)
4803
run_and_verify_svn(None, AnyOutput, [], 'delete', A2)
4588
run_and_verify_svn(AnyOutput, [], 'delete', A2)
4805
4590
# New scenario (starts at the revision before the committed mods)
4806
run_and_verify_svn(None, AnyOutput, [], 'up', A, '-r1')
4807
run_and_verify_svn(None, AnyOutput, [], 'delete', A)
4591
run_and_verify_svn(AnyOutput, [], 'up', A, '-r1')
4592
run_and_verify_svn(AnyOutput, [], 'delete', A)
4809
4594
expected_output = None
4810
4595
expected_disk = None
4905
4690
def modify_dir(dir):
4906
4691
"""Make some set of local modifications to an existing tree:
4907
4692
A prop change, add a child, delete a child, change a child."""
4908
run_and_verify_svn(None, AnyOutput, [],
4693
run_and_verify_svn(AnyOutput, [],
4909
4694
'propset', 'p', 'v', dir)
4910
4695
path = os.path.join(dir, 'new_file')
4911
4696
svntest.main.file_write(path, "This is the file 'new_file'.\n")
4912
svntest.actions.run_and_verify_svn(None, None, [], 'add', path)
4697
svntest.actions.run_and_verify_svn(None, [], 'add', path)
4914
4699
path = os.path.join(dir, 'B', 'lambda')
4915
svntest.actions.run_and_verify_svn(None, None, [], 'delete', path)
4700
svntest.actions.run_and_verify_svn(None, [], 'delete', path)
4917
4702
path = os.path.join(dir, 'B', 'E', 'alpha')
4918
4703
svntest.main.file_append(path, "An extra line.\n")
4920
4705
# Prepare the repos so that a later 'update' has an incoming deletion:
4921
4706
# Delete the dir in the repos, making r2
4922
run_and_verify_svn(None, AnyOutput, [],
4707
run_and_verify_svn(AnyOutput, [],
4923
4708
'-m', '', 'delete', dir_url)
4925
4710
# Existing scenario
5203
4980
### No, we are not checking the merge output for these simple
5204
4981
### merges. This is already covered *TO DEATH* in merge_tests.py.
5206
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
5207
svntest.actions.run_and_verify_svn(None, None, [],
4983
svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir)
4984
svntest.actions.run_and_verify_svn(None, [],
5208
4985
'merge', '-c3', '--depth', 'empty',
5209
4986
sbox.repo_url + '/A', A_COPY_path)
5210
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
4987
svntest.actions.run_and_verify_svn(None, [], 'ci', '-m',
5211
4988
'Merge r3 from A to A_COPY at depth empty',
5213
4990
# Merge -c5 from A to A_COPY (at default --depth infinity), commit as r8.
5214
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
5215
svntest.actions.run_and_verify_svn(None, None, [],
4991
svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir)
4992
svntest.actions.run_and_verify_svn(None, [],
5216
4993
'merge', '-c5',
5217
4994
sbox.repo_url + '/A', A_COPY_path)
5218
svntest.actions.run_and_verify_svn(None, None, [], 'ci', '-m',
4995
svntest.actions.run_and_verify_svn(None, [], 'ci', '-m',
5219
4996
'Merge r5 from A to A_COPY', wc_dir)
5221
4998
# Update WC to r7, repeat merge of -c3 from A to A_COPY but this
5222
4999
# time do it at --depth infinity. Confirm that the mergeinfo
5223
5000
# on A_COPY is no longer inheritable.
5224
svntest.actions.run_and_verify_svn(None, None, [], 'up', '-r7', wc_dir)
5225
svntest.actions.run_and_verify_svn(None, None, [],
5001
svntest.actions.run_and_verify_svn(None, [], 'up', '-r7', wc_dir)
5002
svntest.actions.run_and_verify_svn(None, [],
5226
5003
'merge', '-c3', '--depth', 'infinity',
5227
5004
sbox.repo_url + '/A', A_COPY_path)
5228
svntest.actions.run_and_verify_svn(None, [A_COPY_path + " - /A:3\n"], [],
5005
svntest.actions.run_and_verify_svn([A_COPY_path + " - /A:3\n"], [],
5229
5006
'pg', SVN_PROP_MERGEINFO, '-R',
6576
6332
wc_dir = sbox.wc_dir
6578
svntest.actions.run_and_verify_svnmucc(None, None, [],
6579
'-U', sbox.repo_url,
6334
mucc_url = sbox.repo_url
6336
if mucc_url.startswith('http'):
6337
# Apache Httpd doesn't allow creating paths with '\\' in them on Windows
6338
# AH00026: found %2f (encoded '/') in URI (decoded='/svn-test-work/repositories/authz_tests-30/!svn/ver/2/A/completely\\unusable\\dir'), returning 404
6340
# Let's use file:// to work around.
6341
mucc_url = 'file:///' + os.path.abspath(sbox.repo_dir).replace('\\', '/')
6343
svntest.actions.run_and_verify_svnmucc(None, [],
6581
6346
'mkdir', 'A/completely\\unusable\\dir')
6583
6348
# No error and a proper skip + recording in the working copy would also
6584
6349
# be a good result. This just verifies current behavior.
6586
expected_error = 'svn: E155000: .* is not valid.*'
6587
svntest.actions.run_and_verify_svn(wc_dir, None, expected_error, 'up',
6351
if sbox.repo_url.startswith('http'):
6352
# Apache Httpd doesn't allow paths with '\\' in them on Windows, so the
6353
# test if a user is allowed to read them returns a failure. This makes
6354
# mod_dav_svn report the path as server excluded (aka absent), which
6355
# doesn't produce output when updating.
6357
"Updating '%s':\n" % wc_dir,
6362
expected_output = None
6363
expected_err = 'svn: E155000: .* is not valid.*'
6365
svntest.actions.run_and_verify_svn(expected_output, expected_err,
6368
if sbox.repo_url.startswith('http'):
6369
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
6370
svntest.actions.run_and_verify_status(wc_dir, expected_status)
6590
6372
def update_moved_away(sbox):
6591
6373
"update subtree of moved away"
6769
6545
'A/B/E' : Item(status='A ', wc_rev='-'),
6770
6546
'A/B/E/alpha' : Item(status='A ', wc_rev='-'),
6548
expected_output = svntest.wc.State(wc_dir, {
6549
'A/B/E' : Item(verb='Skipped'),
6772
6551
# Update should still skip A/B/E
6773
6552
svntest.actions.run_and_verify_update(wc_dir,
6774
6553
expected_output,
6776
6555
expected_status,
6779
6557
sbox.ospath('A/B/E'))
6559
def update_conflict_details(sbox):
6560
"update conflict details"
6563
wc_dir = sbox.wc_dir
6565
sbox.simple_append('A/B/E/new', 'new\n')
6566
sbox.simple_add('A/B/E/new')
6567
sbox.simple_append('A/B/E/alpha', '\nextra\nlines\n')
6568
sbox.simple_rm('A/B/E/beta', 'A/B/F')
6569
sbox.simple_propset('key', 'VAL', 'A/B/E', 'A/B')
6570
sbox.simple_mkdir('A/B/E/new-dir1')
6571
sbox.simple_mkdir('A/B/E/new-dir2')
6572
sbox.simple_mkdir('A/B/E/new-dir3')
6573
sbox.simple_rm('A/B/lambda')
6574
sbox.simple_mkdir('A/B/lambda')
6575
sbox.simple_commit()
6577
sbox.simple_update('', 1)
6579
sbox.simple_propset('key', 'vAl', 'A/B')
6580
sbox.simple_move('A/B/E/beta', 'beta')
6581
sbox.simple_propset('a', 'b', 'A/B/F', 'A/B/lambda')
6582
sbox.simple_append('A/B/E/alpha', 'other\nnew\nlines')
6583
sbox.simple_mkdir('A/B/E/new')
6584
sbox.simple_mkdir('A/B/E/new-dir1')
6585
sbox.simple_append('A/B/E/new-dir2', 'something')
6586
sbox.simple_append('A/B/E/new-dir3', 'something')
6587
sbox.simple_add('A/B/E/new-dir3')
6589
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
6590
expected_status.add({
6591
'A/B/E/new' : Item(status='R ', treeconflict='C', wc_rev='2'),
6592
'A/B/E/new-dir2' : Item(status='D ', treeconflict='C', wc_rev='2'),
6593
'A/B/E/new-dir3' : Item(status='R ', treeconflict='C', wc_rev='2'),
6594
'A/B/E/new-dir1' : Item(status=' ', wc_rev='2'),
6595
'A/C' : Item(status=' ', wc_rev='2'),
6596
'iota' : Item(status=' ', wc_rev='2'),
6597
'beta' : Item(status='A ', copied='+', wc_rev='-')
6599
expected_status.tweak('A/B', status=' C', wc_rev='2')
6600
expected_status.tweak('A/B/E/alpha', status='C ', wc_rev='2')
6601
expected_status.tweak('A/B/E/beta', status='! ', treeconflict='C', wc_rev=None)
6602
expected_status.tweak('A/B/F', status='A ', copied='+', treeconflict='C', wc_rev='-')
6603
expected_status.tweak('A/B/lambda', status='RM', copied='+', treeconflict='C', wc_rev='-')
6604
expected_status.tweak('A/mu', status=' ', wc_rev='2')
6605
expected_output = svntest.wc.State(wc_dir, {
6606
'A/B' : Item(status=' C'),
6607
'A/B/E' : Item(status=' U'),
6608
'A/B/E/new' : Item(status=' ', treeconflict='C'),
6609
'A/B/E/beta' : Item(status=' ', treeconflict='C'),
6610
'A/B/E/alpha' : Item(status='C '),
6611
'A/B/E/new-dir2' : Item(status=' ', treeconflict='C'),
6612
'A/B/E/new-dir3' : Item(status=' ', treeconflict='C'),
6613
'A/B/E/new-dir1' : Item(status='E '),
6614
'A/B/F' : Item(status=' ', treeconflict='C'),
6615
# ### 2 tree conflict reports; one for delete; one for add...
6616
'A/B/lambda' : Item(status=' ', treeconflict='A',
6617
prev_status=' ', prev_treeconflict='C'),
6619
svntest.actions.run_and_verify_update(wc_dir, expected_output,
6620
None, expected_status)
6622
# Update can't pass source as none at a specific URL@revision,
6623
# because it doesn't know... the working copy could be mixed
6624
# revision or may have excluded parts...
6627
"Path" : re.escape(sbox.ospath('A/B')),
6629
"Conflict Properties File" :
6630
re.escape(sbox.ospath('A/B/dir_conflicts.prej')) + '.*',
6631
"Conflict Details": re.escape(
6632
'incoming dir edit upon update' +
6633
' Source left: (dir) ^/A/B@1' +
6634
' Source right: (dir) ^/A/B@2')
6637
"Path" : re.escape(sbox.ospath('A/B/E')),
6640
"Path" : re.escape(sbox.ospath('A/B/E/alpha')),
6641
"Conflict Previous Base File" : '.*alpha.*',
6642
"Conflict Previous Working File" : '.*alpha.*',
6643
"Conflict Current Base File": '.*alpha.*',
6644
"Conflict Details": re.escape(
6645
'incoming file edit upon update' +
6646
' Source left: (file) ^/A/B/E/alpha@1' +
6647
' Source right: (file) ^/A/B/E/alpha@2')
6650
"Path" : re.escape(sbox.ospath('A/B/E/beta')),
6651
"Tree conflict": re.escape(
6652
'local file moved away, incoming file delete or move upon update' +
6653
' Source left: (file) ^/A/B/E/beta@1' +
6654
' Source right: (none) ^/A/B/E/beta@2')
6657
"Path" : re.escape(sbox.ospath('A/B/E/new')),
6658
"Tree conflict": re.escape(
6659
'local dir add, incoming file add upon update' +
6660
' Source left: (none)' +
6661
' Source right: (file) ^/A/B/E/new@2')
6664
"Path" : re.escape(sbox.ospath('A/B/E/new-dir1')),
6665
# No tree conflict. Existing directory taken over
6668
"Path" : re.escape(sbox.ospath('A/B/E/new-dir2')),
6669
"Tree conflict": re.escape(
6670
'local file unversioned, incoming dir add upon update' +
6671
' Source left: (none)' +
6672
' Source right: (dir) ^/A/B/E/new-dir2@2')
6675
"Path" : re.escape(sbox.ospath('A/B/E/new-dir3')),
6676
"Tree conflict": re.escape(
6677
'local file add, incoming dir add upon update' +
6678
' Source left: (none)' +
6679
' Source right: (dir) ^/A/B/E/new-dir3@2')
6682
"Path" : re.escape(sbox.ospath('A/B/F')),
6683
"Tree conflict": re.escape(
6684
'local dir edit, incoming dir delete or move upon update' +
6685
' Source left: (dir) ^/A/B/F@1' +
6686
' Source right: (none) ^/A/B/F@2')
6689
"Path" : re.escape(sbox.ospath('A/B/lambda')),
6690
"Tree conflict": re.escape(
6691
'local file edit, incoming replace with dir upon update' +
6692
' Source left: (file) ^/A/B/lambda@1' +
6693
' Source right: (dir) ^/A/B/lambda@2')
6697
svntest.actions.run_and_verify_info(expected_info, sbox.ospath('A/B'),
6698
'--depth', 'infinity')
6782
6700
#######################################################################
6783
6701
# Run the tests