3
# move_tests.py: testing the local move tracking
5
# Subversion is a tool for revision control.
6
# See http://subversion.apache.org for more information.
8
# ====================================================================
9
# Licensed to the Apache Software Foundation (ASF) under one
10
# or more contributor license agreements. See the NOTICE file
11
# distributed with this work for additional information
12
# regarding copyright ownership. The ASF licenses this file
13
# to you under the Apache License, Version 2.0 (the
14
# "License"); you may not use this file except in compliance
15
# with the License. You may obtain a copy of the License at
17
# http://www.apache.org/licenses/LICENSE-2.0
19
# Unless required by applicable law or agreed to in writing,
20
# software distributed under the License is distributed on an
21
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22
# KIND, either express or implied. See the License for the
23
# specific language governing permissions and limitations
25
######################################################################
29
import os, re, logging
31
logger = logging.getLogger()
35
from svntest import wc, actions, verify
38
Skip = svntest.testcase.Skip_deco
39
SkipUnless = svntest.testcase.SkipUnless_deco
40
XFail = svntest.testcase.XFail_deco
41
Issues = svntest.testcase.Issues_deco
42
Issue = svntest.testcase.Issue_deco
43
Wimp = svntest.testcase.Wimp_deco
44
Item = svntest.wc.StateItem
45
exp_noop_up_out = svntest.actions.expected_noop_update_output
47
def build_incoming_changes_file(sbox, source, dest):
48
"Build up revs to receive incoming changes over our local file move"
50
# r1 = greek tree sandbox
52
# r2 = Modify source of moved file
53
sbox.simple_append(source, "modified\n")
54
sbox.simple_commit(message="Modify source of moved file")
56
# r3 = Delete source of moved file
57
sbox.simple_rm(source)
58
sbox.simple_commit(message="Delete source of moved file")
60
# r4 = Replace source of moved file
61
# To get a replace update from r2 to r4.
62
sbox.simple_add_text("This is the replaced file.\n", source)
63
sbox.simple_commit(message="Replace source of moved file")
65
# r5 = Add destination of moved file
66
sbox.simple_add_text("This is the destination file.\n", dest)
67
sbox.simple_commit(message="Add destination of moved file")
69
# r6 = Modify destination of moved file
70
sbox.simple_append(dest, "modified\n")
71
sbox.simple_commit(message="Modify destination of moved file")
73
# r7 = Delete destination of moved file
75
sbox.simple_commit(message="Delete destination of moved file")
77
# r8 = Copy destination of moved file
78
sbox.simple_copy('A/mu', dest)
79
sbox.simple_commit(message="Copy destination of moved file")
81
# r9 = Replace destination of moved file
83
sbox.simple_add_text("This is the destination file.\n", dest)
84
sbox.simple_commit(message="Replace destination of moved file")
86
# r10 = Add property on destination of moved file.
87
sbox.simple_propset("foo", "bar", dest)
88
sbox.simple_commit(message="Add property on destination of moved file")
90
# r11 = Modify property on destination of moved file.
91
sbox.simple_propset("foo", "baz", dest)
92
sbox.simple_commit(message="Modify property on destination of moved file")
94
# r12 = Delete property on destination of moved file.
95
sbox.simple_propdel("foo", dest)
96
sbox.simple_commit(message="Delete property on destination of moved file")
98
# r13 = Remove destination again (not needed for any test just cleanup).
100
sbox.simple_commit(message="Remove destination (cleanup)")
102
# r14 = Add property on source of moved file.
103
sbox.simple_propset("foo", "bar", source)
104
sbox.simple_commit(message="Add property on source of moved file")
106
# r15 = Modify property on source of moved file.
107
sbox.simple_propset("foo", "baz", source)
108
sbox.simple_commit(message="Modify property on source of moved file")
110
# r16 = Delete property on source of moved file.
111
sbox.simple_propdel("foo", source)
112
sbox.simple_commit(message="Delete property on source of moved file")
114
# r17 = Move that is identical to our local move.
115
sbox.simple_move(source, dest)
116
sbox.simple_commit(message="Identical move to our local move")
118
def move_file_test(sbox, source, dest, move_func, test):
119
"""Execute a series of actions to test local move tracking. sbox is the
120
sandbox we're working in, source is the source of the move, dest is the
121
destination for the move and tests is various other parameters of the move
122
testing. In particular:
123
start_rev: revision to update to before starting
124
start_output: validate the output of the start update against this.
125
start_disk: validate the on disk state after the start update against this.
126
start_status: validate the wc status after the start update against this.
127
end_rev: revision to update to, bringing in some update you want to test.
128
up_output: validate the output of the end update agianst this.
129
up_disk: validate the on disk state after the end update against this.
130
up_status: validate the wc status after the end update against this.
131
revert_paths: validate the paths reverted.
132
resolves: A directory of resolve accept arguments to test, the whole test will
133
be run for each. The value is a directory with the following keys:
134
output: validate the output of the resolve command against this.
135
error: validate the error of the resolve command against this.
136
status: validate the wc status after the resolve against this.
137
revert_paths: override the paths reverted check in the test."""
141
source_path = sbox.ospath(source)
142
dest_path = sbox.ospath(dest)
144
# Deal with if there's no resolves key, as in we're not going to
146
if not 'resolves' in test or not test['resolves']:
147
test['resolves'] = {None: None}
149
# Do the test for every type of resolve provided.
150
for resolve_accept in test['resolves'].keys():
152
# update to start_rev
153
svntest.actions.run_and_verify_update(wc_dir, test['start_output'],
154
test['start_disk'], test['start_status'],
155
None, None, None, None, None, False,
156
'-r', test['start_rev'], wc_dir)
158
move_func(test['start_rev'])
160
# update to end_rev, which will create a conflict
161
# TODO: Limit the property checks to only when we're doing something with
163
svntest.actions.run_and_verify_update(wc_dir, test['up_output'],
164
test['up_disk'], test['up_status'],
165
None, None, None, None, None, True,
166
'-r', test['end_rev'], wc_dir)
169
if 'revert_paths' in test:
170
revert_paths = test['revert_paths']
172
# resolve the conflict
173
# TODO: Switch to using run_and_verify_resolve, can't use it right now because
174
# it's not friendly with the output of resolutions right now.
176
resolve = test['resolves'][resolve_accept]
177
if not 'output' in resolve:
178
resolve['output'] = None
179
if not 'error' in resolve:
180
resolve['error'] = []
181
if not 'disk' in resolve:
182
resolve['disk'] = None
183
if 'revert_paths' in resolve:
184
revert_paths = resolve['revert_paths']
185
svntest.actions.run_and_verify_svn('Resolve modification to source of move',
186
resolve['output'], resolve['error'],
187
'resolve', '--accept', resolve_accept,
190
# TODO: This should be moved into the run_and_verify_resolve mentioned
192
if resolve['status']:
193
svntest.actions.run_and_verify_status(wc_dir, resolve['status'])
195
# TODO: This should be moved into the run_and_verify_resolve mentioned
198
svntest.actions.verify_disk(wc_dir, resolve['disk'], True)
200
# revert to preprare for the next test
201
svntest.actions.run_and_verify_revert(revert_paths, '-R', wc_dir)
203
# tests is an array of test dictionaries that move_file_test above will take
204
def move_file_tests(sbox, source, dest, move_func, tests):
206
move_file_test(sbox, source, dest, move_func, test)
208
def build_simple_file_move_tests(sbox, source, dest):
209
"""Given a sandbox, source and destination build the array of tests for
213
source_path = sbox.ospath(source)
214
dest_path = sbox.ospath(dest)
216
# Build the tests list
219
# move and update with incoming change to source (r1-2).
221
test['start_rev'] = 1
223
test['start_output'] = None
224
test['start_disk'] = None
225
test['start_status'] = None
226
test['up_output'] = svntest.wc.State(wc_dir, {
227
source : Item(status=' ', treeconflict='C'),
229
test['up_disk'] = svntest.main.greek_state.copy()
230
test['up_disk'].add({
231
dest: Item("This is the file 'lambda'.\n")
233
test['up_disk'].remove(source)
234
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
235
test['up_status'].tweak(source, status='D ', moved_to=dest,
237
test['up_status'].add({dest: Item(status='A ', moved_from=source,
238
copied='+', wc_rev='-')})
240
mc['output'] = svntest.verify.ExpectedOutput(
241
"Resolved conflicted state of '%s'\n" % source_path, match_all=False
243
mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
244
mc['status'].tweak(source, status='D ', moved_to=dest)
245
mc['status'].add({dest: Item(status='A ', moved_from=source,
246
copied='+', wc_rev='-')})
247
mc['disk'] = test['up_disk'].copy()
248
mc['disk'].tweak(dest, contents="This is the file 'lambda'.\nmodified\n")
249
# theirs-conflict doesn't work
251
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
252
tc['status'] = test['up_status']
253
tc['disk'] = test['up_disk']
254
# working breaks the move
256
working['output'] = svntest.verify.ExpectedOutput(
258
"Breaking move with source path '%s'\n" % source_path,
259
"Resolved conflicted state of '%s'\n" % source_path,
262
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
263
working['status'].tweak(source, status='D ')
264
working['status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
265
working['disk'] = test['up_disk']
266
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
268
test['revert_paths'] = [source_path, dest_path]
271
# move and update with incoming deletion of source (r2-3)
273
test['start_rev'] = 2
275
test['start_output'] = None
276
test['start_disk'] = None
277
test['start_status'] = None
278
test['up_output'] = svntest.wc.State(wc_dir, {
279
source : Item(status=' ', treeconflict='C'),
281
test['up_disk'] = svntest.main.greek_state.copy()
282
test['up_disk'].add({
283
dest: Item("This is the file 'lambda'.\nmodified\n")
285
test['up_disk'].remove(source)
286
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
287
test['up_status'].tweak(source, status='! ', treeconflict='C', wc_rev=None)
288
test['up_status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
289
# mine-conflict and theirs-conflict don't work.
291
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
292
mc['status'] = test['up_status']
293
mc['disk'] = test['up_disk']
295
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
296
tc['status'] = test['up_status']
297
tc['disk'] = test['up_disk']
299
# XXX: Doesn't say it broke the move it should.
300
working['output'] = svntest.verify.ExpectedOutput(
301
"Resolved conflicted state of '%s'\n" % source_path, match_all=False
304
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
305
working['status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
306
working['status'].remove(source)
307
working['disk'] = test['up_disk']
308
working['revert_paths'] = [dest_path]
309
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
311
test['revert_paths'] = [dest_path, source_path]
314
# move and update with incoming replacement of source (r2-4)
316
test['start_rev'] = 2
318
test['start_output'] = None
319
test['start_disk'] = None
320
test['start_status'] = None
321
test['up_output'] = svntest.wc.State(wc_dir, {
322
source : Item(status=' ', prev_status=' ', treeconflict='A',
323
prev_treeconflict='C'),
325
test['up_disk'] = svntest.main.greek_state.copy()
326
test['up_disk'].add({
327
dest: Item("This is the file 'lambda'.\nmodified\n")
329
test['up_disk'].remove(source)
330
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
331
# XXX: Is entry_status=' ' really right here?
332
test['up_status'].tweak(source, status='! ', treeconflict='C', entry_status=' ')
333
test['up_status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
334
# mine-conflict and theirs-conflict don't work.
336
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
337
mc['status'] = test['up_status']
338
mc['disk'] = test['up_disk']
340
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
341
tc['status'] = test['up_status']
342
tc['disk'] = test['up_disk']
344
# XXX: Broke the move but doesn't notify that it does.
345
working['output'] = svntest.verify.ExpectedOutput(
346
"Resolved conflicted state of '%s'\n" % source_path, match_all=False
348
# XXX: Not sure this status is really correct here
349
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
350
working['status'].tweak(source, status='! ')
351
working['status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
352
working['disk'] = test['up_disk']
353
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
355
test['revert_paths'] = [source_path, dest_path]
358
# move and update with incoming add of dest (r4-5)
360
test['start_rev'] = 4
362
test['start_output'] = None
363
test['start_disk'] = None
364
test['start_status'] = None
365
test['up_output'] = svntest.wc.State(wc_dir, {
366
dest : Item(status=' ', treeconflict='C'),
368
test['up_disk'] = svntest.main.greek_state.copy()
369
test['up_disk'].add({
370
dest: Item("This is the replaced file.\n")
372
test['up_disk'].remove(source)
373
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
374
test['up_status'].tweak(source, status='D ', moved_to=dest)
375
test['up_status'].add({dest: Item(status='R ', copied='+', treeconflict='C',
376
wc_rev='-', moved_from=source)})
377
# mine-conflict and theirs-conflict don't work.
379
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
380
mc['status'] = test['up_status']
381
mc['disk'] = test['up_disk']
383
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
384
tc['status'] = test['up_status']
385
tc['disk'] = test['up_disk']
387
# XXX: Doesn't say what it did.
388
working['output'] = svntest.verify.ExpectedOutput(
389
"Resolved conflicted state of '%s'\n" % dest_path, match_all=False
391
# working converts the move into a replacement
392
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
393
working['status'].tweak(source, status='D ', moved_to=dest)
394
working['status'].add({dest: Item(status='R ', moved_from=source,
395
copied='+', wc_rev='-')})
396
working['disk'] = test['up_disk']
397
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
399
test['revert_paths'] = [source_path, dest_path]
402
# move and update with incoming add of dest (r4-6)
403
# we're going 4-6 because we're not testing a replacement move
405
test['start_rev'] = 4
407
test['start_output'] = None
408
test['start_disk'] = None
409
test['start_status'] = None
410
test['up_output'] = svntest.wc.State(wc_dir, {
411
dest : Item(status=' ', treeconflict='C'),
413
test['up_disk'] = svntest.main.greek_state.copy()
414
test['up_disk'].add({
415
dest: Item("This is the replaced file.\n")
417
test['up_disk'].remove(source)
418
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
419
test['up_status'].tweak(source, status='D ', moved_to=dest)
420
test['up_status'].add({dest: Item(status='R ', copied='+', treeconflict='C',
421
wc_rev='-', moved_from=source)})
422
# mine-conflict and theirs-conflict don't work.
424
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
425
mc['status'] = test['up_status']
426
mc['disk'] = test['up_disk']
428
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
429
tc['status'] = test['up_status']
430
tc['disk'] = test['up_disk']
432
working['accept'] = 'working'
433
# XXX: Doesn't say what it did.
434
working['output'] = svntest.verify.ExpectedOutput(
435
"Resolved conflicted state of '%s'\n" % dest_path, match_all=False
437
# working converts the move into a replacement
438
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
439
working['status'].tweak(source, status='D ', moved_to=dest)
440
working['status'].add({dest: Item(status='R ', moved_from=source,
441
copied='+', wc_rev='-')})
442
working['disk'] = test['up_disk']
443
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
445
test['revert_paths'] = [source_path, dest_path]
448
# move and update with incoming delete of dest (r4-7)
449
# Since we're not testing a replacement move the incoming delete has to
450
# be done starting from a rev where the file doesn't exist. So it ends
451
# up being a no-op update. So this test might be rather pointless.
453
test['start_rev'] = 4
455
test['start_output'] = None
456
test['start_disk'] = None
457
test['start_status'] = None
458
test['up_output'] = svntest.wc.State(wc_dir, { })
459
test['up_disk'] = svntest.main.greek_state.copy()
460
test['up_disk'].add({
461
dest: Item("This is the replaced file.\n")
463
test['up_disk'].remove(source)
464
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
465
test['up_status'].tweak(source, status='D ', moved_to=dest)
466
test['up_status'].add({dest: Item(status='A ', copied='+',
467
wc_rev='-', moved_from=source)})
468
# no conflict so no resolve.
469
test['revert_paths'] = [source_path, dest_path]
472
# move and update with incoming copy to dest (r7-8)
474
test['start_rev'] = 7
476
test['start_output'] = None
477
test['start_disk'] = None
478
test['start_status'] = None
479
test['up_output'] = svntest.wc.State(wc_dir, {
480
dest : Item(status=' ', treeconflict='C'),
482
test['up_disk'] = svntest.main.greek_state.copy()
483
test['up_disk'].add({
484
dest: Item("This is the replaced file.\n")
486
test['up_disk'].remove(source)
487
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
488
test['up_status'].tweak(source, status='D ', moved_to=dest)
489
test['up_status'].add({dest: Item(status='R ', copied='+', treeconflict='C',
490
wc_rev='-', moved_from=source)})
491
# mine-conflict and theirs-conflict don't work.
493
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
494
mc['status'] = test['up_status']
495
mc['disk'] = test['up_disk']
497
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
498
tc['status'] = test['up_status']
499
tc['disk'] = test['up_disk']
501
# XXX: Doesn't say what it did.
502
working['output'] = svntest.verify.ExpectedOutput(
503
"Resolved conflicted state of '%s'\n" % dest_path, match_all=False
505
# working converts the move into a replacement
506
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
507
working['status'].tweak(source, status='D ', moved_to=dest)
508
working['status'].add({dest: Item(status='R ', moved_from=source,
509
copied='+', wc_rev='-')})
510
working['disk'] = test['up_disk']
511
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
513
test['revert_paths'] = [source_path, dest_path]
516
# move and update with incoming replace to dest (r7-9)
518
test['start_rev'] = 7
520
test['start_output'] = None
521
test['start_disk'] = None
522
test['start_status'] = None
523
test['up_output'] = svntest.wc.State(wc_dir, {
524
dest : Item(status=' ', treeconflict='C'),
526
test['up_disk'] = svntest.main.greek_state.copy()
527
test['up_disk'].add({
528
dest: Item("This is the replaced file.\n")
530
test['up_disk'].remove(source)
531
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
532
test['up_status'].tweak(source, status='D ', moved_to=dest)
533
test['up_status'].add({dest: Item(status='R ', copied='+', treeconflict='C',
534
wc_rev='-', moved_from=source)})
535
# mine-conflict and theirs-conflict don't work.
537
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
538
mc['status'] = test['up_status']
539
mc['disk'] = test['up_disk']
541
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
542
tc['status'] = test['up_status']
543
tc['disk'] = test['up_disk']
545
# XXX: Doesn't say what it did.
546
working['output'] = svntest.verify.ExpectedOutput(
547
"Resolved conflicted state of '%s'\n" % dest_path, match_all=False
549
# working converts the move into a replacement
550
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
551
working['status'].tweak(source, status='D ', moved_to=dest)
552
working['status'].add({dest: Item(status='R ', moved_from=source,
553
copied='+', wc_rev='-')})
554
working['disk'] = test['up_disk']
555
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
557
test['revert_paths'] = [source_path, dest_path]
560
# move and update with incoming property addition to dest (r7-10)
562
test['start_rev'] = 7
564
test['start_output'] = None
565
test['start_disk'] = None
566
test['start_status'] = None
567
test['up_output'] = svntest.wc.State(wc_dir, {
568
dest : Item(status=' ', treeconflict='C'),
570
test['up_disk'] = svntest.main.greek_state.copy()
571
test['up_disk'].add({
572
dest: Item("This is the replaced file.\n")
574
test['up_disk'].remove(source)
575
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
576
test['up_status'].tweak(source, status='D ', moved_to=dest)
577
test['up_status'].add({dest: Item(status='R ', copied='+', treeconflict='C',
578
wc_rev='-', moved_from=source)})
579
# mine-conflict and theirs-conflict don't work.
581
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
582
mc['status'] = test['up_status']
583
mc['disk'] = test['up_disk']
585
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
586
tc['status'] = test['up_status']
587
tc['disk'] = test['up_disk']
589
# XXX: Didn't tell us what it did.
590
working['output'] = svntest.verify.ExpectedOutput(
591
"Resolved conflicted state of '%s'\n" % dest_path, match_all=False
593
# working converts the move into a replacement
594
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
595
working['status'].tweak(source, status='D ', moved_to=dest)
596
working['status'].add({dest: Item(status='R ', moved_from=source,
597
copied='+', wc_rev='-')})
598
working['disk'] = test['up_disk']
599
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
601
test['revert_paths'] = [source_path, dest_path]
604
# move and update with incoming property modification to dest (r7-11)
606
test['start_rev'] = 7
608
test['start_output'] = None
609
test['start_disk'] = None
610
test['start_status'] = None
611
test['up_output'] = svntest.wc.State(wc_dir, {
612
dest : Item(status=' ', treeconflict='C'),
614
test['up_disk'] = svntest.main.greek_state.copy()
615
test['up_disk'].add({
616
dest: Item("This is the replaced file.\n")
618
test['up_disk'].remove(source)
619
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
620
test['up_status'].tweak(source, status='D ', moved_to=dest)
621
test['up_status'].add({dest: Item(status='R ', copied='+', treeconflict='C',
622
wc_rev='-', moved_from=source)})
623
# mine-conflict and theirs-conflict don't work.
625
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
626
mc['status'] = test['up_status']
627
mc['disk'] = test['up_disk']
629
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
630
tc['status'] = test['up_status']
631
tc['disk'] = test['up_disk']
633
# XXX: Doesn't tell you what it did.
634
working['output'] = svntest.verify.ExpectedOutput(
635
"Resolved conflicted state of '%s'\n" % dest_path, match_all=False
637
# working converts the move into a replacement
638
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
639
working['status'].tweak(source, status='D ', moved_to=dest)
640
working['status'].add({dest: Item(status='R ', moved_from=source,
641
copied='+', wc_rev='-')})
642
working['disk'] = test['up_disk']
643
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
645
test['revert_paths'] = [source_path, dest_path]
648
# move and update with incoming property deletion to dest (r7-12)
650
test['start_rev'] = 7
652
test['start_output'] = None
653
test['start_disk'] = None
654
test['start_status'] = None
655
test['up_output'] = svntest.wc.State(wc_dir, {
656
dest : Item(status=' ', treeconflict='C'),
658
test['up_disk'] = svntest.main.greek_state.copy()
659
test['up_disk'].add({
660
dest: Item("This is the replaced file.\n")
662
test['up_disk'].remove(source)
663
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
664
test['up_status'].tweak(source, status='D ', moved_to=dest)
665
test['up_status'].add({dest: Item(status='R ', copied='+', treeconflict='C',
666
wc_rev='-', moved_from=source)})
667
# mine-conflict and theirs-conflict don't work.
669
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
670
mc['status'] = test['up_status']
671
mc['disk'] = test['up_disk']
673
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
674
tc['status'] = test['up_status']
675
tc['disk'] = test['up_disk']
677
# XXX: Doesn't tell you what it did.
678
working['output'] = svntest.verify.ExpectedOutput(
679
"Resolved conflicted state of '%s'\n" % dest_path, match_all=False
681
# working converts the move into a replacement
682
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
683
working['status'].tweak(source, status='D ', moved_to=dest)
684
working['status'].add({dest: Item(status='R ', moved_from=source,
685
copied='+', wc_rev='-')})
686
working['disk'] = test['up_disk']
687
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
689
test['revert_paths'] = [source_path, dest_path]
692
# move and update with incoming property addition to source (r13-14)
694
test['start_rev'] = 13
696
test['start_output'] = None
697
test['start_disk'] = None
698
test['start_status'] = None
699
test['up_output'] = svntest.wc.State(wc_dir, {
700
source : Item(status=' ', treeconflict='C'),
702
test['up_disk'] = svntest.main.greek_state.copy()
703
test['up_disk'].add({
704
dest: Item("This is the replaced file.\n")
706
test['up_disk'].remove(source)
707
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
708
test['up_status'].tweak(source, status='D ', moved_to=dest, treeconflict='C')
709
test['up_status'].add({dest: Item(status='A ', copied='+', wc_rev='-',
712
# TODO: Should check that the output includes that the update was applied to
714
mc['output'] = svntest.verify.ExpectedOutput(
715
"Resolved conflicted state of '%s'\n" % source_path, match_all=False
717
mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
718
mc['status'].tweak(source, status='D ', moved_to=dest)
719
mc['status'].add({dest: Item(status='A ', moved_from=source,
720
copied='+', wc_rev='-')})
721
mc['disk'] = test['up_disk'].copy()
722
mc['disk'].tweak(dest, props={u'foo': u'bar'})
723
# theirs-conflict doesn't work
725
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
726
tc['status'] = test['up_status']
727
tc['disk'] = test['up_disk']
729
working['output'] = svntest.verify.ExpectedOutput(
731
"Breaking move with source path '%s'\n" % source_path,
732
"Resolved conflicted state of '%s'\n" % source_path
735
# XXX: working breaks the move? Is that right?
736
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
737
working['status'].tweak(source, status='D ')
738
working['status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
739
working['disk'] = test['up_disk']
740
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
742
test['revert_paths'] = [source_path, dest_path]
745
# move and update with incoming property modification to source (r14-15)
747
test['start_rev'] = 14
749
test['start_output'] = None
750
test['start_disk'] = None
751
test['start_status'] = None
752
test['up_output'] = svntest.wc.State(wc_dir, {
753
source : Item(status=' ', treeconflict='C'),
755
test['up_disk'] = svntest.main.greek_state.copy()
756
test['up_disk'].add({
757
dest: Item("This is the replaced file.\n", props={u'foo': u'bar'})
759
test['up_disk'].remove(source)
760
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
761
test['up_status'].tweak(source, status='D ', moved_to=dest, treeconflict='C')
762
test['up_status'].add({dest: Item(status='A ', copied='+', wc_rev='-',
765
# TODO: Should check that the output includes that the update was applied to
767
mc['output'] = svntest.verify.ExpectedOutput(
768
"Resolved conflicted state of '%s'\n" % source_path, match_all=False
770
mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
771
mc['status'].tweak(source, status='D ', moved_to=dest)
772
mc['status'].add({dest: Item(status='A ', moved_from=source,
773
copied='+', wc_rev='-')})
774
mc['disk'] = test['up_disk'].copy()
775
mc['disk'].tweak(dest, props={u'foo': u'baz'})
776
# theirs-conflict doesn't work
778
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
779
tc['status'] = test['up_status']
780
tc['disk'] = test['up_disk']
782
working['output'] = svntest.verify.ExpectedOutput(
784
"Breaking move with source path '%s'\n" % source_path,
785
"Resolved conflicted state of '%s'\n" % source_path
788
# XXX: working breaks the move? Is that right?
789
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
790
working['status'].tweak(source, status='D ')
791
working['status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
792
working['disk'] = test['up_disk']
793
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
795
test['revert_paths'] = [source_path, dest_path]
798
# move and update with incoming property deletion to source (r15-16)
800
test['start_rev'] = 15
802
test['start_output'] = None
803
test['start_disk'] = None
804
test['start_status'] = None
805
test['up_output'] = svntest.wc.State(wc_dir, {
806
source : Item(status=' ', treeconflict='C'),
808
test['up_disk'] = svntest.main.greek_state.copy()
809
test['up_disk'].add({
810
dest: Item("This is the replaced file.\n", props={'foo': 'baz'})
812
test['up_disk'].remove(source)
813
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
814
test['up_status'].tweak(source, status='D ', moved_to=dest, treeconflict='C')
815
test['up_status'].add({dest: Item(status='A ', copied='+', wc_rev='-',
818
# TODO: Should check that the output includes that the update was applied to
820
mc['output'] = svntest.verify.ExpectedOutput(
821
"Resolved conflicted state of '%s'\n" % source_path, match_all=False
823
mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
824
mc['status'].tweak(source, status='D ', moved_to=dest)
825
mc['status'].add({dest: Item(status='A ', moved_from=source,
826
copied='+', wc_rev='-')})
827
mc['disk'] = test['up_disk'].copy()
828
mc['disk'].tweak(dest, props={})
829
# theirs-conflict doesn't work
831
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
832
tc['status'] = test['up_status']
833
tc['disk'] = test['up_disk']
835
working['output'] = svntest.verify.ExpectedOutput(
837
"Breaking move with source path '%s'\n" % source_path,
838
"Resolved conflicted state of '%s'\n" % source_path
841
# XXX: working breaks the move? Is that right?
842
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
843
working['status'].tweak(source, status='D ')
844
working['status'].add({dest: Item(status='A ', copied='+', wc_rev='-')})
845
working['disk'] = test['up_disk']
846
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
848
test['revert_paths'] = [source_path, dest_path]
851
# move and update with incoming identical move (r16-17)
852
# XXX: It'd be really nice if we actually recognized this and the wc
853
# showed no conflict at all on udpate.
855
test['start_rev'] = 16
857
test['start_output'] = None
858
test['start_disk'] = None
859
test['start_status'] = None
860
test['up_output'] = svntest.wc.State(wc_dir, {
861
source : Item(status=' ', treeconflict='C'),
862
dest : Item(status=' ', treeconflict='C'),
864
test['up_disk'] = svntest.main.greek_state.copy()
865
test['up_disk'].add({
866
dest: Item("This is the replaced file.\n")
868
test['up_disk'].remove(source)
869
test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
870
test['up_status'].tweak(source, status='! ', treeconflict='C', wc_rev=None)
871
test['up_status'].add({dest: Item(status='R ', copied='+', wc_rev='-',
873
# mine-conflict and theirs-conflict don't work.
875
mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
876
mc['status'] = test['up_status']
877
mc['disk'] = test['up_disk']
879
tc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False)
880
tc['status'] = test['up_status']
881
tc['disk'] = test['up_disk']
883
working['output'] = svntest.verify.ExpectedOutput(
884
"Resolved conflicted state of '%s'\n" % source_path, match_all=False
887
working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev'])
888
working['status'].add({dest: Item(status='R ', copied='+', wc_rev='-')})
889
working['status'].remove(source)
890
working['disk'] = test['up_disk']
891
working['revert_paths'] = [dest_path]
892
test['resolves'] = {'mine-conflict': mc, 'theirs-conflict': tc,
894
test['revert_paths'] = [dest_path, source_path]
899
def build_simple_file_move_func(sbox, source, dest):
901
source_path = sbox.ospath(source)
902
dest_path = sbox.ospath(dest)
904
# Setup the move function
907
svntest.actions.run_and_verify_svn(None, None, [], "move",
908
source_path, dest_path)
909
if move_func.extra_mv_tests:
910
mv_status = svntest.actions.get_virginal_state(wc_dir, rev)
911
mv_status.tweak(source, status='D ', moved_to=dest)
912
mv_status.add({dest: Item(status='A ', moved_from=source,
913
copied='+', wc_rev='-')})
916
'Path' : re.escape(source_path),
917
'Moved To' : re.escape(dest),
922
'Path' : re.escape(dest_path),
923
'Moved From' : re.escape(source),
927
# check the status output.
928
svntest.actions.run_and_verify_status(wc_dir, mv_status)
930
# check the info output
931
svntest.actions.run_and_verify_info(mv_info_src, source_path)
932
svntest.actions.run_and_verify_info(mv_info_dst, dest_path)
933
move_func.extra_mv_tests = False
935
# Do the status and info tests the first time through
936
# No reason to repeat these tests for each of the variations below
937
# since the move is exactly the same.
938
move_func.extra_mv_tests = True
942
######################################################################
945
# Each test must return on success or raise on failure.
947
# See http://wiki.apache.org/subversion/LocalMoves
949
def lateral_move_file_test(sbox):
950
"lateral (rename) move of a file test"
953
# Plan to test moving A/B/lambda to A/B/lambda-moved
954
source = 'A/B/lambda'
955
dest = 'A/B/lambda-moved'
957
# Build the revisions to do the updates via
958
build_incoming_changes_file(sbox, source, dest)
960
# Get function to implement the actual move
961
move_func = build_simple_file_move_func(sbox, source, dest)
964
tests = build_simple_file_move_tests(sbox, source, dest)
966
# Actually run the tests
967
move_file_tests(sbox, source, dest, move_func, tests)
969
def sibling_move_file_test(sbox):
970
"sibling move of a file test"
973
# Plan to test moving A/B/lambda to A/C/lambda
974
source = 'A/B/lambda'
977
# Build the revisions to do the updates via
978
build_incoming_changes_file(sbox, source, dest)
980
# Get function to implement the actual move
981
move_func = build_simple_file_move_func(sbox, source, dest)
984
tests = build_simple_file_move_tests(sbox, source, dest)
986
# Actually run the tests
987
move_file_tests(sbox, source, dest, move_func, tests)
989
def shallower_move_file_test(sbox):
990
"shallower move of a file test"
993
# Plan to test moving A/B/lambda to A/lambda
994
source = 'A/B/lambda'
997
# Build the revisions to do the updates via
998
build_incoming_changes_file(sbox, source, dest)
1000
# Get function to implement the actual move
1001
move_func = build_simple_file_move_func(sbox, source, dest)
1004
tests = build_simple_file_move_tests(sbox, source, dest)
1006
# Actually run the tests
1007
move_file_tests(sbox, source, dest, move_func, tests)
1009
def deeper_move_file_test(sbox):
1010
"deeper move of a file test"
1013
# Plan to test moving A/B/lambda to A/B/F/lambda
1014
source = 'A/B/lambda'
1015
dest = 'A/B/F/lambda'
1017
# Build the revisions to do the updates via
1018
build_incoming_changes_file(sbox, source, dest)
1020
# Get function to implement the actual move
1021
move_func = build_simple_file_move_func(sbox, source, dest)
1024
tests = build_simple_file_move_tests(sbox, source, dest)
1026
# Actually run the tests
1027
move_file_tests(sbox, source, dest, move_func, tests)
1030
def property_merge(sbox):
1031
"test property merging on move-update"
1033
# pristine local incoming outcome revert
1034
# 1 p1 v2 p2 v2 p1 v2, p2 v2 p2 v2
1035
# 2 p1 v1 p1 v2 p2 v2 p1 v2, p2 v2 p1 v1 p2 v2
1036
# 3 p1 v1 p1 v2 p1 v2 p1 v2 p1 v2
1037
# 4 p1 v2 p1 v3 p1 v2 conflict p1 v3
1038
# 5 p1 v1 p1 v2 p1 v3 p1 v2 conflict p1 v3
1041
wc_dir = sbox.wc_dir
1043
sbox.simple_mkdir('A/C/D1')
1044
sbox.simple_mkdir('A/C/D2')
1045
sbox.simple_mkdir('A/C/D3')
1046
sbox.simple_mkdir('A/C/D4')
1047
sbox.simple_mkdir('A/C/D5')
1048
sbox.simple_add_text('content of f1', 'A/C/f1')
1049
sbox.simple_add_text('content of f2', 'A/C/f2')
1050
sbox.simple_add_text('content of f3', 'A/C/f3')
1051
sbox.simple_add_text('content of f4', 'A/C/f4')
1052
sbox.simple_add_text('content of f5', 'A/C/f5')
1053
sbox.simple_propset('key1', 'value1',
1054
'A/C/D2', 'A/C/D3', 'A/C/D5',
1055
'A/C/f2', 'A/C/f3', 'A/C/f5')
1056
sbox.simple_commit()
1057
sbox.simple_propset('key2', 'value2',
1060
sbox.simple_propset('key1', 'value2',
1063
sbox.simple_propset('key1', 'value3',
1066
sbox.simple_commit()
1067
sbox.simple_update('', 2)
1068
sbox.simple_propset('key1', 'value2',
1069
'A/C/D1', 'A/C/D2', 'A/C/D3', 'A/C/D4', 'A/C/D5',
1070
'A/C/f1', 'A/C/f2', 'A/C/f3', 'A/C/f4', 'A/C/f5')
1071
sbox.simple_move('A/C', 'A/C2')
1073
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1074
expected_status.tweak('A/C', status='D ', moved_to='A/C2')
1075
expected_status.add({
1076
'A/C/D1' : Item(status='D ', wc_rev=2),
1077
'A/C/D2' : Item(status='D ', wc_rev=2),
1078
'A/C/D3' : Item(status='D ', wc_rev=2),
1079
'A/C/D4' : Item(status='D ', wc_rev=2),
1080
'A/C/D5' : Item(status='D ', wc_rev=2),
1081
'A/C/f1' : Item(status='D ', wc_rev=2),
1082
'A/C/f2' : Item(status='D ', wc_rev=2),
1083
'A/C/f3' : Item(status='D ', wc_rev=2),
1084
'A/C/f4' : Item(status='D ', wc_rev=2),
1085
'A/C/f5' : Item(status='D ', wc_rev=2),
1086
'A/C2' : Item(status='A ', copied='+', wc_rev='-', moved_from='A/C'),
1087
'A/C2/D1' : Item(status=' M', copied='+', wc_rev='-'),
1088
'A/C2/D2' : Item(status=' M', copied='+', wc_rev='-'),
1089
'A/C2/D3' : Item(status=' M', copied='+', wc_rev='-'),
1090
'A/C2/D4' : Item(status=' M', copied='+', wc_rev='-'),
1091
'A/C2/D5' : Item(status=' M', copied='+', wc_rev='-'),
1092
'A/C2/f1' : Item(status=' M', copied='+', wc_rev='-'),
1093
'A/C2/f2' : Item(status=' M', copied='+', wc_rev='-'),
1094
'A/C2/f3' : Item(status=' M', copied='+', wc_rev='-'),
1095
'A/C2/f4' : Item(status=' M', copied='+', wc_rev='-'),
1096
'A/C2/f5' : Item(status=' M', copied='+', wc_rev='-'),
1098
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1100
sbox.simple_update()
1101
svntest.actions.run_and_verify_svn("resolve failed", None, [],
1103
'--accept=mine-conflict',
1106
expected_status.tweak(wc_rev=3)
1107
expected_status.tweak('A/C2',
1108
'A/C2/D1', 'A/C2/D2', 'A/C2/D3', 'A/C2/D4', 'A/C2/D5',
1109
'A/C2/f1', 'A/C2/f2', 'A/C2/f3', 'A/C2/f4', 'A/C2/f5',
1111
expected_status.tweak('A/C2/D3',
1114
expected_status.tweak('A/C2/D4', 'A/C2/D5',
1115
'A/C2/f4', 'A/C2/f5',
1118
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1120
expected_disk = svntest.main.greek_state.copy()
1121
expected_disk.remove('A/C')
1124
'A/C2/D1' : Item(props={'key1' : 'value2', 'key2' : 'value2'}),
1125
'A/C2/D2' : Item(props={'key1' : 'value2', 'key2' : 'value2'}),
1126
'A/C2/D3' : Item(props={'key1' : 'value2'}),
1127
'A/C2/D4' : Item(props={'key1' : 'value2'}),
1128
'A/C2/D5' : Item(props={'key1' : 'value2'}),
1129
'A/C2/f1' : Item(contents='content of f1',
1130
props={'key1' : 'value2', 'key2' : 'value2'}),
1131
'A/C2/f2' : Item(contents='content of f2',
1132
props={'key1' : 'value2', 'key2' : 'value2'}),
1133
'A/C2/f3' : Item(contents='content of f3',
1134
props={'key1' : 'value2'}),
1135
'A/C2/f4' : Item(contents='content of f4',
1136
props={'key1' : 'value2'}),
1137
'A/C2/f5' : Item(contents='content of f5',
1138
props={'key1' : 'value2'}),
1139
'A/C2/D4/dir_conflicts.prej' : Item(contents=
1140
"""Trying to add new property 'key1'
1141
but the property already exists.
1142
<<<<<<< (local property value)
1144
value3>>>>>>> (incoming property value)
1146
'A/C2/D5/dir_conflicts.prej' : Item(contents=
1147
"""Trying to change property 'key1'
1148
but the property has already been locally changed to a different value.
1149
<<<<<<< (local property value)
1151
value3>>>>>>> (incoming property value)
1153
'A/C2/f4.prej' : Item(contents=
1154
"""Trying to add new property 'key1'
1155
but the property already exists.
1156
<<<<<<< (local property value)
1158
value3>>>>>>> (incoming property value)
1160
'A/C2/f5.prej' : Item(contents=
1161
"""Trying to change property 'key1'
1162
but the property has already been locally changed to a different value.
1163
<<<<<<< (local property value)
1165
value3>>>>>>> (incoming property value)
1169
svntest.actions.verify_disk(wc_dir, expected_disk, True)
1171
sbox.simple_revert('A/C2/D1', 'A/C2/D2', 'A/C2/D4', 'A/C2/D5',
1172
'A/C2/f1', 'A/C2/f2', 'A/C2/f4', 'A/C2/f5')
1174
expected_status.tweak('A/C2/D1', 'A/C2/D2', 'A/C2/D4', 'A/C2/D5',
1175
'A/C2/f1', 'A/C2/f2', 'A/C2/f4', 'A/C2/f5',
1177
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1179
expected_disk.remove('A/C2/D4/dir_conflicts.prej',
1180
'A/C2/D5/dir_conflicts.prej',
1183
expected_disk.tweak('A/C2/D1',
1185
props={'key2' : 'value2'})
1186
expected_disk.tweak('A/C2/D2',
1188
props={'key1' : 'value1', 'key2' : 'value2'})
1189
expected_disk.tweak('A/C2/D4', 'A/C2/D5',
1190
'A/C2/f4', 'A/C2/f5',
1191
props={'key1' : 'value3'})
1192
svntest.actions.verify_disk(wc_dir, expected_disk, True)
1196
def move_missing(sbox):
1197
"move a missing directory"
1199
sbox.build(read_only=True)
1200
wc_dir = sbox.wc_dir
1202
svntest.main.safe_rmtree(sbox.ospath('A/D/G'))
1204
expected_err = '.*Can\'t move \'.*G\' to \'.*R\':.*'
1206
# This move currently fails halfway between adding the dest and
1207
# deleting the source
1208
svntest.actions.run_and_verify_svn(None, None, expected_err,
1209
'mv', sbox.ospath('A/D/G'),
1212
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1213
expected_status.tweak('A/D/G', 'A/D/G/tau', 'A/D/G/pi', 'A/D/G/rho',
1214
status='! ', entry_status=' ')
1216
expected_status.add({
1217
'R' : Item(status='! ', wc_rev='-',
1218
entry_status='A ', entry_copied='+'),
1219
'R/pi' : Item(status='! ', wc_rev='-',
1220
entry_status=' ', entry_copied='+'),
1221
'R/tau' : Item(status='! ', wc_rev='-',
1222
entry_status=' ', entry_copied='+'),
1223
'R/rho' : Item(status='! ', wc_rev='-',
1224
entry_status=' ', entry_copied='+'),
1227
# Verify that the status processing doesn't crash
1228
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1230
# The issue is a crash when the destination is present
1231
os.mkdir(sbox.ospath('R'))
1232
expected_status.tweak('R', status='A ', copied='+')
1234
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1237
def setup_move_many(sbox):
1238
"helper function which creates a wc with node A/A/A which is moved 3 times"
1240
sbox.simple_rm('A', 'iota')
1241
sbox.simple_mkdir('A',
1253
sbox.simple_commit()
1254
sbox.simple_update()
1256
sbox.simple_move('A/A/A', 'AAA_1')
1259
sbox.simple_move('B', 'A')
1261
sbox.simple_move('A/A/A', 'AAA_2')
1263
sbox.simple_rm('A/A')
1264
sbox.simple_move('C/A', 'A/A')
1266
sbox.simple_move('A/A/A', 'AAA_3')
1268
def move_many_status(wc_dir):
1269
"obtain standard status after setup_move_many"
1271
return svntest.wc.State(wc_dir, {
1272
'' : Item(status=' ', wc_rev='2'),
1274
'AAA_1' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
1275
'AAA_1/A' : Item(status=' ', copied='+', wc_rev='-'),
1277
'AAA_2' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
1278
'AAA_2/A' : Item(status=' ', copied='+', wc_rev='-'),
1280
'AAA_3' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
1281
'AAA_3/A' : Item(status=' ', copied='+', wc_rev='-'),
1283
'A' : Item(status='R ', copied='+', moved_from='B', wc_rev='-'),
1284
'A/A' : Item(status='R ', copied='+', moved_from='C/A', wc_rev='-'),
1285
'A/A/A' : Item(status='D ', copied='+', wc_rev='-', moved_to='AAA_3'),
1286
'A/A/A/A' : Item(status='D ', copied='+', wc_rev='-'),
1288
'B' : Item(status='D ', wc_rev='2', moved_to='A'),
1289
'B/A' : Item(status='D ', wc_rev='2'),
1290
'B/A/A' : Item(status='D ', wc_rev='2'),
1291
'B/A/A/A' : Item(status='D ', wc_rev='2'),
1293
'C' : Item(status=' ', wc_rev='2'),
1294
'C/A' : Item(status='D ', wc_rev='2', moved_to='A/A'),
1295
'C/A/A' : Item(status='D ', wc_rev='2'),
1296
'C/A/A/A' : Item(status='D ', wc_rev='2'),
1299
def move_many_update_delete(sbox):
1300
"move many and delete-on-update"
1303
setup_move_many(sbox)
1305
wc_dir = sbox.wc_dir
1307
# Verify start situation
1308
expected_status = move_many_status(wc_dir)
1309
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1311
# And now create a tree conflict
1312
svntest.actions.run_and_verify_svn(None, None, [],
1313
'rm', sbox.repo_url + '/B',
1316
expected_output = svntest.wc.State(wc_dir, {
1317
'B' : Item(status=' ', treeconflict='C'),
1321
expected_status.tweak('', 'C', 'C/A', 'C/A/A', 'C/A/A/A', wc_rev='3')
1322
expected_status.tweak('A', moved_from=None)
1323
expected_status.remove('B/A', 'B/A/A', 'B/A/A/A')
1324
expected_status.tweak('B', status='! ', treeconflict='C', wc_rev=None, moved_to=None)
1326
svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
1329
# Would be nice if we could run the resolver as a separate step,
1330
# but 'svn resolve' just fails for any value but working
1333
def move_many_update_add(sbox):
1334
"move many and add-on-update"
1337
setup_move_many(sbox)
1339
wc_dir = sbox.wc_dir
1341
# Verify start situation
1342
expected_status = move_many_status(wc_dir)
1343
#svntest.actions.run_and_verify_status(wc_dir, expected_status)
1345
# And now create a tree conflict
1346
svntest.actions.run_and_verify_svn(None, None, [],
1347
'mkdir', sbox.repo_url + '/B/A/A/BB',
1350
expected_output = svntest.wc.State(wc_dir, {
1351
'B' : Item(status=' ', treeconflict='C'),
1352
'B/A' : Item(status=' ', treeconflict='U'),
1353
'B/A/A' : Item(status=' ', treeconflict='U'),
1354
'B/A/A/BB' : Item(status=' ', treeconflict='A'),
1355
# And while resolving
1356
'A/A/' : Item(status=' ', treeconflict='C')
1359
expected_status.tweak('',
1360
'B', 'B/A', 'B/A/A', 'B/A/A/A',
1361
'C', 'C/A', 'C/A/A', 'C/A/A/A',
1364
expected_status.tweak('A/A', treeconflict='C')
1365
expected_status.add({
1366
'A/A/A/BB' : Item(status='D ', copied='+', wc_rev='-'),
1367
'B/A/A/BB' : Item(status='D ', wc_rev='3'),
1370
svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
1374
wc_dir, '--accept', 'mine-conflict')
1377
svntest.actions.run_and_verify_svn(None, None, [],
1378
'mkdir', sbox.repo_url + '/C/A/A/BB',
1381
expected_status.tweak('',
1382
'B', 'B/A', 'B/A/A', 'B/A/A/A',
1383
'C', 'C/A', 'C/A/A', 'C/A/A/A',
1386
expected_output = svntest.wc.State(wc_dir, {
1387
'C/A' : Item(status=' ', treeconflict='C'),
1388
'C/A/A' : Item(status=' ', treeconflict='U'),
1389
'C/A/A/BB' : Item(status=' ', treeconflict='A'),
1392
# This currently triggers an assertion failure
1393
svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
1397
wc_dir, '--accept', 'mine-conflict')
1400
#######################################################################
1403
# list all tests here, starting with None:
1405
lateral_move_file_test,
1406
sibling_move_file_test,
1407
shallower_move_file_test,
1408
deeper_move_file_test,
1411
move_many_update_delete,
1412
move_many_update_add,
1415
if __name__ == '__main__':
1416
svntest.main.run_tests(test_list)