3
# update_tests.py: testing update cases.
5
# Subversion is a tool for revision control.
6
# See http://subversion.tigris.org for more information.
8
# ====================================================================
9
# Copyright (c) 2000-2004 CollabNet. All rights reserved.
11
# This software is licensed as described in the file COPYING, which
12
# you should have received as part of this distribution. The terms
13
# are also available at http://subversion.tigris.org/license-1.html.
14
# If newer versions of this license are posted there, you may use a
15
# newer version instead, at your option.
17
######################################################################
20
import shutil, string, sys, re, os
24
from svntest import wc, SVNAnyOutput
28
Skip = svntest.testcase.Skip
29
XFail = svntest.testcase.XFail
30
Item = svntest.wc.StateItem
33
######################################################################
36
# Each test must return on success or raise on failure.
39
#----------------------------------------------------------------------
41
# Helper for update_binary_file() test -- a custom singleton handler.
42
def detect_extra_files(node, extra_files):
43
"""NODE has been discovered as an extra file on disk. Verify that
44
it matches one of the regular expressions in the EXTRA_FILES list of
45
lists, and that its contents matches the second part of the list
46
item. If it matches, remove the match from the list. If it doesn't
47
match, raise an exception."""
49
# Baton is of the form:
51
# [ [wc_dir, pattern, contents],
52
# [wc_dir, pattern, contents], ... ]
54
for fdata in extra_files:
60
match_obj = re.match(pattern, node.name)
65
fp = open(os.path.join (wc_dir, node.path))
66
real_contents = fp.read() # suck up contents of a test .png file
68
if real_contents == contents:
69
extra_files.pop(extra_files.index(fdata)) # delete pattern from list
72
print "Found unexpected object:", node.name
73
raise svntest.main.SVNTreeUnequal
77
def update_binary_file(sbox):
78
"update a locally-modified binary file"
83
# Add a binary file to the project.
84
fp = open(os.path.join(sys.path[0], "theta.bin"))
85
theta_contents = fp.read() # suck up contents of a test .png file
88
theta_path = os.path.join(wc_dir, 'A', 'theta')
89
fp = open(theta_path, 'w')
90
fp.write(theta_contents) # write png filedata into 'A/theta'
93
svntest.main.run_svn(None, 'add', theta_path)
95
# Created expected output tree for 'svn ci'
96
expected_output = svntest.wc.State(wc_dir, {
97
'A/theta' : Item(verb='Adding (bin)'),
100
# Create expected status tree
101
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
102
expected_status.tweak(wc_rev=1)
103
expected_status.add({
104
'A/theta' : Item(status=' ', wc_rev=2),
107
# Commit the new binary file, creating revision 2.
108
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
109
expected_status, None,
110
None, None, None, None, wc_dir)
112
# Make a backup copy of the working copy.
113
wc_backup = sbox.add_wc_path('backup')
114
svntest.actions.duplicate_dir(wc_dir, wc_backup)
115
theta_backup_path = os.path.join(wc_backup, 'A', 'theta')
117
# Make a change to the binary file in the original working copy
118
svntest.main.file_append(theta_path, "revision 3 text")
119
theta_contents_r3 = theta_contents + "revision 3 text"
121
# Created expected output tree for 'svn ci'
122
expected_output = svntest.wc.State(wc_dir, {
123
'A/theta' : Item(verb='Sending'),
126
# Create expected status tree
127
expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
128
expected_status.tweak(wc_rev=1)
129
expected_status.add({
130
'A/theta' : Item(status=' ', wc_rev=3),
133
# Commit original working copy again, creating revision 3.
134
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
135
expected_status, None,
136
None, None, None, None, wc_dir)
138
# Now start working in the backup working copy:
140
# Make a local mod to theta
141
svntest.main.file_append(theta_backup_path, "extra theta text")
142
theta_contents_local = theta_contents + "extra theta text"
144
# Create expected output tree for an update of wc_backup.
145
expected_output = svntest.wc.State(wc_backup, {
146
'A/theta' : Item(status='C '),
149
# Create expected disk tree for the update --
150
# look! binary contents, and a binary property!
151
expected_disk = svntest.main.greek_state.copy()
153
'A/theta' : Item(theta_contents_local,
154
props={'svn:mime-type' : 'application/octet-stream'}),
157
# Create expected status tree for the update.
158
expected_status = svntest.actions.get_virginal_state(wc_backup, 3)
159
expected_status.add({
160
'A/theta' : Item(status='C ', wc_rev=3),
163
# Extra 'singleton' files we expect to exist after the update.
164
# In the case, the locally-modified binary file should be backed up
166
# This is a list of lists, of the form [ WC_DIR,
167
# [pattern, contents], ...]
168
extra_files = [[wc_backup, 'theta.*\.r2', theta_contents],
169
[wc_backup, 'theta.*\.r3', theta_contents_r3]]
171
# Do the update and check the results in three ways. Pass our
172
# custom singleton handler to verify the .orig file; this handler
173
# will verify the existence (and contents) of both binary files
174
# after the update finishes.
175
svntest.actions.run_and_verify_update(wc_backup,
180
detect_extra_files, extra_files,
183
# verify that the extra_files list is now empty.
184
if len(extra_files) != 0:
185
print "Not all extra reject files have been accounted for:"
187
raise svntest.Failure
189
#----------------------------------------------------------------------
191
def update_binary_file_2(sbox):
192
"update to an old revision of a binary files"
197
# Suck up contents of a test .png file.
198
fp = open(os.path.join(sys.path[0], "theta.bin"))
199
theta_contents = fp.read()
202
# 102400 is svn_txdelta_window_size. We're going to make sure we
203
# have at least 102401 bytes of data in our second binary file (for
204
# no reason other than we have had problems in the past with getting
205
# svndiff data out of the repository for files > 102400 bytes).
206
# How? Well, we'll just keep doubling the binary contents of the
207
# original theta.png until we're big enough.
208
zeta_contents = theta_contents
209
while(len(zeta_contents) < 102401):
210
zeta_contents = zeta_contents + zeta_contents
212
# Write our two files' contents out to disk, in A/theta and A/zeta.
213
theta_path = os.path.join(wc_dir, 'A', 'theta')
214
fp = open(theta_path, 'w')
215
fp.write(theta_contents)
217
zeta_path = os.path.join(wc_dir, 'A', 'zeta')
218
fp = open(zeta_path, 'w')
219
fp.write(zeta_contents)
222
# Now, `svn add' those two files.
223
svntest.main.run_svn(None, 'add', theta_path, zeta_path)
225
# Created expected output tree for 'svn ci'
226
expected_output = svntest.wc.State(wc_dir, {
227
'A/theta' : Item(verb='Adding (bin)'),
228
'A/zeta' : Item(verb='Adding (bin)'),
231
# Create expected status tree
232
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
233
expected_status.tweak(wc_rev=1)
234
expected_status.add({
235
'A/theta' : Item(status=' ', wc_rev=2),
236
'A/zeta' : Item(status=' ', wc_rev=2),
239
# Commit the new binary filea, creating revision 2.
240
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
241
expected_status, None,
242
None, None, None, None, wc_dir)
244
# Make some mods to the binary files.
245
svntest.main.file_append (theta_path, "foobar")
246
new_theta_contents = theta_contents + "foobar"
247
svntest.main.file_append (zeta_path, "foobar")
248
new_zeta_contents = zeta_contents + "foobar"
250
# Created expected output tree for 'svn ci'
251
expected_output = svntest.wc.State(wc_dir, {
252
'A/theta' : Item(verb='Sending'),
253
'A/zeta' : Item(verb='Sending'),
256
# Create expected status tree
257
expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
258
expected_status.tweak(wc_rev=1)
259
expected_status.add({
260
'A/theta' : Item(status=' ', wc_rev=3),
261
'A/zeta' : Item(status=' ', wc_rev=3),
264
# Commit original working copy again, creating revision 3.
265
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
266
expected_status, None,
267
None, None, None, None, wc_dir)
269
# Create expected output tree for an update to rev 2.
270
expected_output = svntest.wc.State(wc_dir, {
271
'A/theta' : Item(status='U '),
272
'A/zeta' : Item(status='U '),
275
# Create expected disk tree for the update --
276
# look! binary contents, and a binary property!
277
expected_disk = svntest.main.greek_state.copy()
279
'A/theta' : Item(theta_contents,
280
props={'svn:mime-type' : 'application/octet-stream'}),
281
'A/zeta' : Item(zeta_contents,
282
props={'svn:mime-type' : 'application/octet-stream'}),
285
# Create expected status tree for the update.
286
expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
287
expected_status.tweak(wc_rev=2)
288
expected_status.add({
289
'A/theta' : Item(status=' ', wc_rev=2),
290
'A/zeta' : Item(status=' ', wc_rev=2),
293
# Do an update from revision 2 and make sure that our binary file
294
# gets reverted to its original contents.
295
svntest.actions.run_and_verify_update(wc_dir,
304
#----------------------------------------------------------------------
306
def update_missing(sbox):
307
"update missing items (by name) in working copy"
312
# Remove some files and dirs from the working copy.
313
mu_path = os.path.join(wc_dir, 'A', 'mu')
314
rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
315
E_path = os.path.join(wc_dir, 'A', 'B', 'E')
316
H_path = os.path.join(wc_dir, 'A', 'D', 'H')
318
# remove two files to verify that they get restored
322
### FIXME I think directories work because they generate 'A'
323
### feedback, is this the correct feedback?
324
svntest.main.safe_rmtree(E_path)
325
svntest.main.safe_rmtree(H_path)
327
# Create expected output tree for an update of the missing items by name
328
expected_output = svntest.wc.State(wc_dir, {
329
'A/mu' : Item(verb='Restored'),
330
'A/D/G/rho' : Item(verb='Restored'),
331
'A/B/E' : Item(status='A '),
332
'A/B/E/alpha' : Item(status='A '),
333
'A/B/E/beta' : Item(status='A '),
334
'A/D/H' : Item(status='A '),
335
'A/D/H/chi' : Item(status='A '),
336
'A/D/H/omega' : Item(status='A '),
337
'A/D/H/psi' : Item(status='A '),
340
# Create expected disk tree for the update.
341
expected_disk = svntest.main.greek_state.copy()
343
# Create expected status tree for the update.
344
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
346
# Do the update and check the results in three ways.
347
svntest.actions.run_and_verify_update(wc_dir,
351
None, None, None, None, None, 0,
355
#----------------------------------------------------------------------
357
def update_ignores_added(sbox):
358
"update should not munge adds or replaces"
363
# Commit something so there's actually a new revision to update to.
364
rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
365
svntest.main.file_append(rho_path, "\nMore stuff in rho.")
366
svntest.main.run_svn(None, 'ci', '-m', 'log msg', rho_path)
368
# Create a new file, 'zeta', and schedule it for addition.
369
zeta_path = os.path.join(wc_dir, 'A', 'B', 'zeta')
370
svntest.main.file_append(zeta_path, "This is the file 'zeta'.")
371
svntest.main.run_svn(None, 'add', zeta_path)
373
# Schedule another file, say, 'gamma', for replacement.
374
gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
375
svntest.main.run_svn(None, 'delete', gamma_path)
376
svntest.main.file_append(gamma_path, "This is a new 'gamma' now.")
377
svntest.main.run_svn(None, 'add', gamma_path)
379
# Now update. "zeta at revision 0" should *not* be reported at all,
380
# so it should remain scheduled for addition at revision 0. gamma
381
# was scheduled for replacement, so it also should remain marked as
382
# such, and maintain its revision of 1.
384
# Create expected output tree for an update of the wc_backup.
385
expected_output = svntest.wc.State(wc_dir, { })
387
# Create expected disk tree for the update.
388
expected_disk = svntest.main.greek_state.copy()
390
'A/B/zeta' : Item("This is the file 'zeta'."),
392
expected_disk.tweak('A/D/gamma', contents="This is a new 'gamma' now.")
393
expected_disk.tweak('A/D/G/rho',
394
contents="This is the file 'rho'.\nMore stuff in rho.")
396
# Create expected status tree for the update.
397
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
398
expected_status.tweak('A/D/gamma', wc_rev=1, status='R ')
399
expected_status.add({
400
'A/B/zeta' : Item(status='A ', wc_rev=0),
403
# Do the update and check the results in three ways.
404
svntest.actions.run_and_verify_update(wc_dir,
410
#----------------------------------------------------------------------
412
def update_to_rev_zero(sbox):
413
"update to revision 0"
418
iota_path = os.path.join(wc_dir, 'iota')
419
A_path = os.path.join(wc_dir, 'A')
421
# Create expected output tree for an update to rev 0
422
expected_output = svntest.wc.State(wc_dir, {
423
'iota' : Item(status='D '),
424
'A' : Item(status='D '),
427
# Create expected disk tree for the update to rev 0
428
expected_disk = svntest.wc.State(wc_dir, { })
430
# Do the update and check the results.
431
svntest.actions.run_and_verify_update(wc_dir,
435
None, None, None, None, 0,
438
#----------------------------------------------------------------------
440
def receive_overlapping_same_change(sbox):
441
"overlapping identical changes should not conflict"
443
### (See http://subversion.tigris.org/issues/show_bug.cgi?id=682.)
445
### How this test works:
447
### Create working copy foo, modify foo/iota. Duplicate foo,
448
### complete with locally modified iota, to bar. Now we should
457
### Commit the change from foo, then update bar. The repository
458
### change should get folded into bar/iota with no conflict, since
459
### the two modifications are identical.
465
iota_path = os.path.join(wc_dir, 'iota')
466
svntest.main.file_append(iota_path, "\nA change to iota.\n")
468
# Duplicate locally modified wc, giving us the "other" wc.
469
other_wc = sbox.add_wc_path('other')
470
svntest.actions.duplicate_dir(wc_dir, other_wc)
471
other_iota_path = os.path.join(other_wc, 'iota')
473
# Created expected output tree for 'svn ci'
474
expected_output = svntest.wc.State(wc_dir, {
475
'iota' : Item(verb='Sending'),
478
# Create expected status tree
479
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
480
expected_status.tweak(wc_rev=1)
481
expected_status.tweak('iota', wc_rev=2)
483
# Commit the change, creating revision 2.
484
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
485
expected_status, None,
486
None, None, None, None, wc_dir)
488
# Expected output tree for update of other_wc.
489
expected_output = svntest.wc.State(other_wc, {
490
'iota' : Item(status='G '),
493
# Expected disk tree for the update.
494
expected_disk = svntest.main.greek_state.copy()
495
expected_disk.tweak('iota',
496
contents="This is the file 'iota'.\nA change to iota.\n")
498
# Expected status tree for the update.
499
expected_status = svntest.actions.get_virginal_state(other_wc, 2)
501
# Do the update and check the results in three ways.
502
svntest.actions.run_and_verify_update(other_wc,
507
#----------------------------------------------------------------------
509
# Helper for update_to_resolve_text_conflicts() test -- a singleton handler.
510
def detect_conflict_files(node, extra_files):
511
"""NODE has been discovered an extra file on disk. Verify that it
512
matches one of the regular expressions in the EXTRA_FILES list. If
513
it matches, remove the match from the list. If it doesn't match,
514
raise an exception."""
516
for pattern in extra_files:
517
mo = re.match(pattern, node.name)
519
extra_files.pop(extra_files.index(pattern)) # delete pattern from list
522
print "Found unexpected object:", node.name
523
raise svntest.main.SVNTreeUnequal
525
def update_to_resolve_text_conflicts(sbox):
526
"delete files and update to resolve text conflicts"
531
# Make a backup copy of the working copy
532
wc_backup = sbox.add_wc_path('backup')
533
svntest.actions.duplicate_dir(wc_dir, wc_backup)
535
# Make a couple of local mods to files which will be committed
536
mu_path = os.path.join(wc_dir, 'A', 'mu')
537
rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
538
svntest.main.file_append (mu_path, '\nOriginal appended text for mu')
539
svntest.main.file_append (rho_path, '\nOriginal appended text for rho')
540
svntest.main.run_svn (None, 'propset', 'Kubla', 'Khan', rho_path)
542
# Make a couple of local mods to files which will be conflicted
543
mu_path_backup = os.path.join(wc_backup, 'A', 'mu')
544
rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho')
545
svntest.main.file_append (mu_path_backup,
546
'\nConflicting appended text for mu')
547
svntest.main.file_append (rho_path_backup,
548
'\nConflicting appended text for rho')
549
svntest.main.run_svn (None, 'propset', 'Kubla', 'Xanadu', rho_path_backup)
551
# Created expected output tree for 'svn ci'
552
expected_output = svntest.wc.State(wc_dir, {
553
'A/mu' : Item(verb='Sending'),
554
'A/D/G/rho' : Item(verb='Sending'),
557
# Create expected status tree; all local revisions should be at 1,
558
# but mu and rho should be at revision 2.
559
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
560
expected_status.tweak(wc_rev=1)
561
expected_status.tweak('A/mu', wc_rev=2)
562
expected_status.tweak('A/D/G/rho', wc_rev=2, status=' ')
565
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
566
expected_status, None,
567
None, None, None, None, wc_dir)
569
# Create expected output tree for an update of the wc_backup.
570
expected_output = svntest.wc.State(wc_backup, {
571
'A/mu' : Item(status='C '),
572
'A/D/G/rho' : Item(status='CC'),
575
# Create expected disk tree for the update.
576
expected_disk = svntest.main.greek_state.copy()
577
expected_disk.tweak('A/mu', contents= """<<<<<<< .mine
578
This is the file 'mu'.
579
Conflicting appended text for mu=======
580
This is the file 'mu'.
581
Original appended text for mu>>>>>>> .r2
583
expected_disk.tweak('A/D/G/rho', contents="""<<<<<<< .mine
584
This is the file 'rho'.
585
Conflicting appended text for rho=======
586
This is the file 'rho'.
587
Original appended text for rho>>>>>>> .r2
590
# Create expected status tree for the update.
591
expected_status = svntest.actions.get_virginal_state(wc_backup, 2)
592
expected_status.tweak('A/mu', status='C ')
593
expected_status.tweak('A/D/G/rho', status='CC')
595
# "Extra" files that we expect to result from the conflicts.
596
# These are expressed as list of regexps. What a cool system! :-)
597
extra_files = ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine',
598
'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine', 'rho.*\.prej']
600
# Do the update and check the results in three ways.
601
# All "extra" files are passed to detect_conflict_files().
602
svntest.actions.run_and_verify_update(wc_backup,
607
detect_conflict_files,
611
# verify that the extra_files list is now empty.
612
if len(extra_files) != 0:
613
print "didn't get expected extra files"
614
raise svntest.Failure
616
# remove the conflicting files to clear text conflict but not props conflict
617
os.remove(mu_path_backup)
618
os.remove(rho_path_backup)
620
# ### TODO: Can't get run_and_verify_update to work here :-( I get
621
# the error "Unequal Types: one Node is a file, the other is a
622
# directory". Use run_svn and then run_and_verify_status instead
623
stdout_lines, stdout_lines = svntest.main.run_svn(None, 'up', wc_backup)
624
if len (stdout_lines) > 0:
625
print "update 2 failed"
626
raise svntest.Failure
628
# Create expected status tree
629
expected_status = svntest.actions.get_virginal_state(wc_backup, 2)
630
expected_status.tweak('A/D/G/rho', status=' C')
632
svntest.actions.run_and_verify_status(wc_backup, expected_status)
634
#----------------------------------------------------------------------
636
def update_delete_modified_files(sbox):
637
"update that deletes modified files"
643
alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
644
svntest.actions.run_and_verify_svn("Deleting alpha failed", None, [],
647
# Delete a directory containing files
648
G_path = os.path.join(wc_dir, 'A', 'D', 'G')
649
svntest.actions.run_and_verify_svn("Deleting G failed", None, [],
653
svntest.actions.run_and_verify_svn("Committing deletes failed", None, [],
654
'ci', '-m', 'log msg', wc_dir)
656
# ### Update before backdating to avoid obstructed update error for G
657
svntest.actions.run_and_verify_svn("Updating after commit failed", None, [],
660
# Backdate to restore deleted items
661
svntest.actions.run_and_verify_svn("Backdating failed", None, [],
662
'up', '-r', '1', wc_dir)
664
# Modify the file to be deleted, and a file in the directory to be deleted
665
svntest.main.file_append(alpha_path, 'appended alpha text')
666
pi_path = os.path.join(G_path, 'pi')
667
svntest.main.file_append(pi_path, 'appended pi text')
669
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
670
expected_status.tweak('A/B/E/alpha', 'A/D/G/pi', status='M ')
672
svntest.actions.run_and_verify_status(wc_dir, expected_status)
674
# Now update to 'delete' modified files -- that is, remove them from
675
# version control, but leave them on disk. It used to be we would
676
# expect an 'obstructed update' error (see issue #1196), but
677
# nowadays we expect success (see issue #1806).
678
expected_output = svntest.wc.State(wc_dir, {
679
'A/B/E/alpha' : Item(status='D '),
680
'A/D/G' : Item(status='D '),
682
expected_disk = svntest.main.greek_state.copy()
683
expected_disk.tweak('A/B/E/alpha',
684
contents="This is the file 'alpha'.appended alpha text")
685
expected_disk.tweak('A/D/G/pi',
686
contents="This is the file 'pi'.appended pi text")
687
expected_disk.remove('A/D/G/rho')
688
expected_disk.remove('A/D/G/tau')
689
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
690
expected_status.remove('A/B/E/alpha')
691
expected_status.remove('A/D/G')
692
expected_status.remove('A/D/G/pi')
693
expected_status.remove('A/D/G/rho')
694
expected_status.remove('A/D/G/tau')
695
svntest.actions.run_and_verify_update(wc_dir,
701
#----------------------------------------------------------------------
703
# Issue 847. Doing an add followed by a remove for an item in state
704
# "deleted" caused the "deleted" state to get forgotten
706
def update_after_add_rm_deleted(sbox):
707
"update after add/rm of deleted state"
712
# Delete a file and directory from WC
713
alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
714
F_path = os.path.join(wc_dir, 'A', 'B', 'F')
715
svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path, F_path)
718
expected_output = svntest.wc.State(wc_dir, {
719
'A/B/E/alpha' : Item(verb='Deleting'),
720
'A/B/F' : Item(verb='Deleting'),
722
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
723
expected_status.tweak(wc_rev=1)
724
expected_status.remove('A/B/E/alpha')
725
expected_status.remove('A/B/F')
726
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
727
expected_status, None,
728
None, None, None, None, wc_dir)
730
# alpha and F are now in state "deleted", next we add a new ones
731
svntest.main.file_append(alpha_path, "new alpha")
732
svntest.actions.run_and_verify_svn(None, None, [], 'add', alpha_path)
734
svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', F_path)
736
# New alpha and F should be in add state A
737
expected_status.add({
738
'A/B/E/alpha' : Item(status='A ', wc_rev=0),
739
'A/B/F' : Item(status='A ', wc_rev=0),
741
svntest.actions.run_and_verify_status(wc_dir, expected_status)
743
# Forced removal of new alpha and F must restore "deleted" state
745
svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--force',
747
if os.path.exists(alpha_path) or os.path.exists(F_path):
748
raise svntest.Failure
750
# "deleted" state is not visible in status
751
expected_status.remove('A/B/E/alpha', 'A/B/F')
752
svntest.actions.run_and_verify_status(wc_dir, expected_status)
754
# Although parent dir is already at rev 1, the "deleted" state will cause
755
# alpha and F to be restored in the WC when updated to rev 1
756
svntest.actions.run_and_verify_svn(None, None, [], 'up', '-r', '1', wc_dir)
757
expected_status.add({
758
'A/B/E/alpha' : Item(status=' ', wc_rev=1),
759
'A/B/F' : Item(status=' ', wc_rev=1),
761
svntest.actions.run_and_verify_status(wc_dir, expected_status)
763
#----------------------------------------------------------------------
765
# Issue 1591. Updating a working copy which contains local
766
# obstructions marks a directory as incomplete. Removal of the
767
# obstruction and subsequent update should clear the "incomplete"
770
def obstructed_update_alters_wc_props(sbox):
771
"obstructed update alters WC properties"
776
# Create a new dir in the repo in prep for creating an obstruction.
777
#print "Adding dir to repo"
778
svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', '-m',
779
'prep for obstruction',
780
sbox.repo_url + '/A/foo')
782
# Create an obstruction, a file in the WC with the same name as
783
# present in a newer rev of the repo.
784
#print "Creating obstruction"
785
obstruction_parent_path = os.path.join(wc_dir, 'A')
786
obstruction_path = os.path.join(obstruction_parent_path, 'foo')
787
svntest.main.file_append(obstruction_path, 'an obstruction')
789
# Update the WC to that newer rev to trigger the obstruction.
791
expected_output = svntest.wc.State(wc_dir, {})
792
expected_disk = svntest.main.greek_state.copy()
793
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
794
error_re = 'Failed to add directory.*object of the same name already exists'
795
svntest.actions.run_and_verify_update(wc_dir,
801
# Remove the file which caused the obstruction.
802
#print "Removing obstruction"
803
os.unlink(obstruction_path)
805
# Update the -- now unobstructed -- WC again.
806
#print "Updating WC again"
807
expected_output = svntest.wc.State(wc_dir, {
808
'A/foo' : Item(status='A '),
810
expected_disk = svntest.main.greek_state.copy()
814
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
815
expected_status.add({
816
'A/foo' : Item(status=' ', wc_rev=2),
818
svntest.actions.run_and_verify_update(wc_dir,
823
# The previously obstructed resource should now be in the WC.
824
if not os.path.isdir(obstruction_path):
825
raise svntest.Failure
827
#----------------------------------------------------------------------
830
def update_replace_dir(sbox):
831
"update that replaces a directory"
837
F_path = os.path.join(wc_dir, 'A', 'B', 'F')
838
svntest.actions.run_and_verify_svn(None, None, [], 'rm', F_path)
841
expected_output = svntest.wc.State(wc_dir, {
842
'A/B/F' : Item(verb='Deleting'),
844
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
845
expected_status.tweak(wc_rev=1)
846
expected_status.remove('A/B/F')
847
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
848
expected_status, None,
849
None, None, None, None, wc_dir)
851
# Add replacement directory
852
svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', F_path)
855
expected_output = svntest.wc.State(wc_dir, {
856
'A/B/F' : Item(verb='Adding'),
858
expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
859
expected_status.tweak(wc_rev=1)
860
expected_status.tweak('A/B/F', wc_rev=3)
861
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
862
expected_status, None,
863
None, None, None, None, wc_dir)
866
expected_output = svntest.wc.State(wc_dir, {
868
expected_disk = svntest.main.greek_state.copy()
869
expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
870
svntest.actions.run_and_verify_update(wc_dir,
875
# Update to revision 1 replaces the directory
876
### I can't get this to work :-(
877
#expected_output = svntest.wc.State(wc_dir, {
878
# 'A/B/F' : Item(verb='Adding'),
879
# 'A/B/F' : Item(verb='Deleting'),
881
#expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
882
#svntest.actions.run_and_verify_update(wc_dir,
886
# None, None, None, None, None, 0,
889
# Update to revision 1 replaces the directory
890
svntest.actions.run_and_verify_svn(None, None, [], 'up', '-r', '1', wc_dir)
891
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
892
svntest.actions.run_and_verify_status(wc_dir, expected_status)
894
#----------------------------------------------------------------------
896
def update_single_file(sbox):
897
"update with explicit file target"
902
expected_disk = svntest.main.greek_state.copy()
904
# Make a local mod to a file which will be committed
905
mu_path = os.path.join(wc_dir, 'A', 'mu')
906
svntest.main.file_append (mu_path, '\nAppended text for mu')
909
expected_output = svntest.wc.State(wc_dir, {
910
'A/mu' : Item(verb='Sending'),
912
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
913
expected_status.tweak(wc_rev=1)
914
expected_status.tweak('A/mu', wc_rev=2)
915
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
916
expected_status, None,
917
None, None, None, None, wc_dir)
919
# At one stage 'svn up file' failed with a parent lock error
920
was_cwd = os.getcwd()
921
os.chdir(os.path.join(wc_dir, 'A'))
924
### Can't get run_and_verify_update to work having done the chdir.
925
svntest.actions.run_and_verify_svn("update failed", None, [],
926
'up', '-r', '1', 'mu')
930
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
931
svntest.actions.run_and_verify_status(wc_dir, expected_status)
933
#----------------------------------------------------------------------
934
def prop_update_on_scheduled_delete(sbox):
935
"receive prop update to file scheduled for deletion"
940
other_wc = sbox.add_wc_path('other')
942
# Make the "other" working copy.
943
svntest.actions.duplicate_dir(wc_dir, other_wc)
945
iota_path = os.path.join(wc_dir, 'iota')
946
other_iota_path = os.path.join(other_wc, 'iota')
948
svntest.main.run_svn (None, 'propset', 'foo', 'bar', iota_path)
950
# Created expected output tree for 'svn ci'
951
expected_output = svntest.wc.State(wc_dir, {
952
'iota' : Item(verb='Sending'),
955
# Create expected status tree
956
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
957
expected_status.tweak(wc_rev=1)
958
expected_status.tweak('iota', wc_rev=2)
960
# Commit the change, creating revision 2.
961
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
962
expected_status, None,
963
None, None, None, None, wc_dir)
965
svntest.main.run_svn (None, 'rm', other_iota_path)
967
# Expected output tree for update of other_wc.
968
expected_output = svntest.wc.State(other_wc, {
969
'iota' : Item(status=' U'),
972
# Expected disk tree for the update.
973
expected_disk = svntest.main.greek_state.copy()
974
expected_disk.remove('iota')
976
# Expected status tree for the update.
977
expected_status = svntest.actions.get_virginal_state(other_wc, 2)
978
expected_status.tweak('iota', status='D ')
980
# Do the update and check the results in three ways.
981
svntest.actions.run_and_verify_update(other_wc,
986
#----------------------------------------------------------------------
988
def update_receive_illegal_name(sbox):
989
"bail when receive a file or dir named .svn"
994
# This tests the revision 4334 fix for issue #1068.
996
legal_url = svntest.main.current_repo_url + '/A/D/G/svn'
997
illegal_url = svntest.main.current_repo_url + '/A/D/G/.svn'
998
# Ha! The client doesn't allow us to mkdir a '.svn' but it does
999
# allow us to copy to a '.svn' so ...
1000
svntest.actions.run_and_verify_svn(None, None, [],
1001
'mkdir', '-m', 'log msg',
1003
svntest.actions.run_and_verify_svn(None, None, [],
1004
'mv', '-m', 'log msg',
1005
legal_url, illegal_url)
1007
# Do the update twice, both should fail. After the first failure
1008
# the wc will be marked "incomplete".
1010
out, err = svntest.main.run_svn(1, 'up', wc_dir)
1012
if line.find("object of the same name already exists") != -1:
1015
raise svntest.Failure
1017
# At one stage an obstructed update in an incomplete wc would leave
1019
out, err = svntest.main.run_svnadmin('lstxns', sbox.repo_dir)
1021
raise svntest.Failure
1023
#----------------------------------------------------------------------
1025
def update_deleted_missing_dir(sbox):
1026
"update missing dir to rev in which it is absent"
1029
wc_dir = sbox.wc_dir
1031
E_path = os.path.join(wc_dir, 'A', 'B', 'E')
1032
H_path = os.path.join(wc_dir, 'A', 'D', 'H')
1034
# Create a new revision with directories deleted
1035
svntest.main.run_svn(None, 'rm', E_path)
1036
svntest.main.run_svn(None, 'rm', H_path)
1037
svntest.main.run_svn(None, 'ci', '-m', 'log msg', E_path, H_path)
1039
# Update back to the old revision
1040
svntest.main.run_svn(None, 'up', '-r', '1', wc_dir)
1042
# Delete the directories from disk
1043
svntest.main.safe_rmtree(E_path)
1044
svntest.main.safe_rmtree(H_path)
1046
# Create expected output tree for an update of the missing items by name
1047
expected_output = svntest.wc.State(wc_dir, {
1048
'A/B/E' : Item(status='D '),
1049
'A/D/H' : Item(status='D '),
1052
# Create expected disk tree for the update.
1053
expected_disk = svntest.main.greek_state.copy()
1054
expected_disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
1055
expected_disk.remove('A/D/H', 'A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi')
1057
# Create expected status tree for the update.
1058
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1059
expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
1060
expected_status.remove('A/D/H', 'A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi')
1061
expected_status.tweak(wc_rev=1)
1063
# Do the update, specifying the deleted paths explicitly.
1064
svntest.actions.run_and_verify_update(wc_dir,
1068
None, None, None, None, None,
1069
0, "-r", "2", E_path, H_path)
1071
# Update back to the old revision again
1072
svntest.main.run_svn(None, 'up', '-r', '1', wc_dir)
1074
# Delete the directories from disk
1075
svntest.main.safe_rmtree(E_path)
1076
svntest.main.safe_rmtree(H_path)
1078
# This time we're updating the whole working copy
1079
expected_status.tweak(wc_rev=2)
1081
# Do the update, on the whole working copy this time
1082
svntest.actions.run_and_verify_update(wc_dir,
1086
None, None, None, None, None,
1087
0, "-r", "2", wc_dir)
1089
#----------------------------------------------------------------------
1091
# Issue 919. This test was written as a regression test for "item
1092
# should remain 'deleted' when an update deletes a sibling".
1093
def another_hudson_problem(sbox):
1094
"another \"hudson\" problem: updates that delete"
1097
wc_dir = sbox.wc_dir
1099
# Delete/commit gamma thus making it 'deleted'
1100
gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
1101
svntest.main.run_svn(None, 'rm', gamma_path)
1102
expected_output = svntest.wc.State(wc_dir, {
1103
'A/D/gamma' : Item(verb='Deleting'),
1105
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1106
expected_status.tweak(wc_rev=1)
1107
expected_status.remove('A/D/gamma')
1108
svntest.actions.run_and_verify_commit (wc_dir,
1111
None, None, None, None, None,
1114
# Delete directory G from the repository
1115
svntest.actions.run_and_verify_svn(None,
1116
['\n', 'Committed revision 3.\n'], None,
1117
'rm', '-m', 'log msg',
1118
svntest.main.current_repo_url + '/A/D/G')
1120
# Remove corresponding tree from working copy
1121
G_path = os.path.join(wc_dir, 'A', 'D', 'G')
1122
svntest.main.safe_rmtree(G_path)
1124
# Update missing directory to receive the delete, this should mark G
1125
# as 'deleted' and should not alter gamma's entry.
1127
# Sigh, I can't get run_and_verify_update to work (but not because
1128
# of issue 919 as far as I can tell)
1129
svntest.actions.run_and_verify_svn(None,
1131
'Updated to revision 3.\n'], None,
1134
# Both G and gamma should be 'deleted', update should produce no output
1135
expected_output = svntest.wc.State(wc_dir, { })
1136
expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
1137
expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
1139
expected_disk = svntest.main.greek_state.copy()
1140
expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
1142
svntest.actions.run_and_verify_update(wc_dir,
1147
#----------------------------------------------------------------------
1148
def update_deleted_targets(sbox):
1149
"explicit update of deleted=true targets"
1152
wc_dir = sbox.wc_dir
1154
# Delete/commit thus creating 'deleted=true' entries
1155
gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
1156
F_path = os.path.join(wc_dir, 'A', 'B', 'F')
1157
svntest.main.run_svn(None, 'rm', gamma_path, F_path)
1158
expected_output = svntest.wc.State(wc_dir, {
1159
'A/D/gamma' : Item(verb='Deleting'),
1160
'A/B/F' : Item(verb='Deleting'),
1162
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1163
expected_status.tweak(wc_rev=1)
1164
expected_status.remove('A/D/gamma', 'A/B/F')
1165
svntest.actions.run_and_verify_commit (wc_dir,
1168
None, None, None, None, None,
1171
# Explicit update must not remove the 'deleted=true' entries
1172
svntest.actions.run_and_verify_svn(None, ['At revision 2.\n'], None,
1173
'update', gamma_path)
1174
svntest.actions.run_and_verify_svn(None, ['At revision 2.\n'], None,
1177
# Update to r1 to restore items, since the parent directory is already
1178
# at r1 this fails if the 'deleted=true' entries are missing (issue 2250)
1179
expected_output = svntest.wc.State(wc_dir, {
1180
'A/D/gamma' : Item(status='A '),
1181
'A/B/F' : Item(status='A '),
1183
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1184
expected_disk = svntest.main.greek_state.copy()
1185
expected_status.tweak(wc_rev=1)
1186
svntest.actions.run_and_verify_update(wc_dir,
1190
None, None, None, None, None, 0,
1195
#----------------------------------------------------------------------
1197
def new_dir_with_spaces(sbox):
1198
"receive new dir with spaces in its name"
1201
wc_dir = sbox.wc_dir
1203
# Create a new directory ("spacey dir") directly in repository
1204
svntest.actions.run_and_verify_svn(None,
1205
['\n', 'Committed revision 2.\n'], None,
1206
'mkdir', '-m', 'log msg',
1207
svntest.main.current_repo_url
1208
+ '/A/spacey%20dir')
1210
# Update, and make sure ra_dav doesn't choke on the space.
1211
expected_output = svntest.wc.State(wc_dir, {
1212
'A/spacey dir' : Item(status='A '),
1214
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1215
expected_status.add({
1216
'A/spacey dir' : Item(status=' ', wc_rev=2),
1218
expected_disk = svntest.main.greek_state.copy()
1220
'A/spacey dir' : Item(),
1223
svntest.actions.run_and_verify_update(wc_dir,
1228
#----------------------------------------------------------------------
1230
def non_recursive_update(sbox):
1231
"non-recursive update"
1234
wc_dir = sbox.wc_dir
1236
# Commit a change to A/mu and A/D/G/rho
1237
mu_path = os.path.join(wc_dir, 'A', 'mu')
1238
rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
1239
svntest.main.file_append(mu_path, "new")
1240
svntest.main.file_append(rho_path, "new")
1241
expected_output = svntest.wc.State(wc_dir, {
1242
'A/mu' : Item(verb='Sending'),
1243
'A/D/G/rho' : Item(verb='Sending'),
1245
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1246
expected_status.tweak(wc_rev=1)
1247
expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2)
1248
svntest.actions.run_and_verify_commit (wc_dir, expected_output,
1250
None, None, None, None, None,
1253
# Update back to revision 1
1254
expected_output = svntest.wc.State(wc_dir, {
1255
'A/mu' : Item(status='U '),
1256
'A/D/G/rho' : Item(status='U '),
1258
expected_disk = svntest.main.greek_state.copy()
1259
expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=1)
1260
svntest.actions.run_and_verify_update(wc_dir, expected_output,
1261
expected_disk, expected_status,
1262
None, None, None, None, None, 0,
1265
# Non-recursive update of A should change A/mu but not A/D/G/rho
1266
A_path = os.path.join(wc_dir, 'A')
1267
expected_output = svntest.wc.State(wc_dir, {
1268
'A/mu' : Item(status='U '),
1270
expected_status.tweak('A', 'A/mu', wc_rev=2)
1271
expected_disk.tweak('A/mu', contents="This is the file 'mu'.new")
1272
svntest.actions.run_and_verify_update(wc_dir, expected_output,
1273
expected_disk, expected_status,
1274
None, None, None, None, None, 0,
1277
#----------------------------------------------------------------------
1279
def checkout_empty_dir(sbox):
1280
"check out an empty dir"
1281
# See issue #1472 -- checked out empty dir should not be marked as
1282
# incomplete ("!" in status).
1284
wc_dir = sbox.wc_dir
1286
C_url = svntest.main.current_repo_url + '/A/C'
1288
svntest.main.safe_rmtree(wc_dir)
1289
svntest.actions.run_and_verify_svn(None, None, [], 'checkout', C_url, wc_dir)
1291
svntest.actions.run_and_verify_svn(None, [], [], 'status', wc_dir)
1294
#----------------------------------------------------------------------
1295
# Regression test for issue #919: "another ghudson bug". Basically, if
1296
# we fore- or back-date an item until it no longer exists, we were
1297
# completely removing the entry, rather than marking it 'deleted'
1298
# (which we now do.)
1300
def update_to_deletion(sbox):
1301
"update target till it's gone, then get it back"
1304
wc_dir = sbox.wc_dir
1306
iota_path = os.path.join(wc_dir, 'iota')
1308
# Update iota to rev 0, so it gets removed.
1309
expected_output = svntest.wc.State(wc_dir, {
1310
'iota' : Item(status='D '),
1312
expected_disk = svntest.main.greek_state.copy()
1313
expected_disk.remove('iota')
1315
svntest.actions.run_and_verify_update(wc_dir,
1319
None, None, None, None, 0,
1320
'-r', '0', iota_path)
1322
# Update the wc root, so iota comes back.
1323
expected_output = svntest.wc.State(wc_dir, {
1324
'iota' : Item(status='A '),
1326
expected_disk = svntest.main.greek_state.copy()
1328
svntest.actions.run_and_verify_update(wc_dir,
1332
None, None, None, None, 0,
1336
#----------------------------------------------------------------------
1338
def update_deletion_inside_out(sbox):
1339
"update child before parent of a deleted tree"
1342
wc_dir = sbox.wc_dir
1344
parent_path = os.path.join(wc_dir, 'A', 'B')
1345
child_path = os.path.join(parent_path, 'E') # Could be a file, doesn't matter
1347
# Delete the parent directory.
1348
svntest.actions.run_and_verify_svn(None, None, [],
1350
svntest.actions.run_and_verify_svn(None, None, [],
1351
'ci', '-m', '', wc_dir)
1353
# Update back to r1.
1354
svntest.actions.run_and_verify_svn(None, None, [],
1355
'update', '-r', '1', wc_dir)
1357
# Update just the child to r2.
1358
svntest.actions.run_and_verify_svn(None, None, [],
1359
'update', '-r', '2', child_path)
1361
# Now try a normal update.
1362
expected_output = svntest.wc.State(wc_dir, {
1363
'A/B' : Item(status='D '),
1365
expected_disk = svntest.main.greek_state.copy()
1366
expected_disk.remove('A/B', 'A/B/lambda', 'A/B/F',
1367
'A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
1369
svntest.actions.run_and_verify_update(wc_dir,
1375
#----------------------------------------------------------------------
1376
# Regression test for issue #1793, whereby 'svn up dir' would delete
1377
# dir if schedule-add. Yikes.
1379
def update_schedule_add_dir(sbox):
1380
"update a schedule-add directory"
1383
wc_dir = sbox.wc_dir
1385
# Delete directory A/D/G in the repository via immediate commit
1386
G_path = os.path.join(wc_dir, 'A', 'D', 'G')
1387
G_url = svntest.main.current_repo_url + '/A/D/G'
1388
svntest.actions.run_and_verify_svn(None, None, [],
1389
'rm', G_url, '-m', 'rev 2')
1391
# Update the wc to HEAD (r2)
1392
expected_output = svntest.wc.State(wc_dir, {
1393
'A/D/G' : Item(status='D '),
1395
expected_disk = svntest.main.greek_state.copy()
1396
expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1397
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1398
expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1399
svntest.actions.run_and_verify_update(wc_dir,
1404
# Do a URL->wc copy, creating a new schedule-add A/D/G.
1405
# (Standard procedure when trying to resurrect the directory.)
1406
D_path = os.path.join(wc_dir, 'A', 'D')
1407
svntest.actions.run_and_verify_svn("Copy error:", None, [],
1408
'cp', '-r', '1', G_url, D_path)
1410
# status should now show the dir scheduled for addition-with-history
1411
expected_status.add({
1412
'A/D/G' : Item(status='A ', copied='+', wc_rev='-'),
1413
'A/D/G/pi' : Item(status=' ', copied='+', wc_rev='-'),
1414
'A/D/G/rho' : Item(status=' ', copied='+', wc_rev='-'),
1415
'A/D/G/tau' : Item(status=' ', copied='+', wc_rev='-'),
1417
svntest.actions.run_and_verify_status (wc_dir, expected_status)
1419
# Now update with the schedule-add dir as the target.
1420
svntest.actions.run_and_verify_svn(None, None, [], 'up', G_path)
1422
# The update should be a no-op, and the schedule-add directory
1423
# should still exist! 'svn status' shouldn't change at all.
1424
svntest.actions.run_and_verify_status (wc_dir, expected_status)
1427
#----------------------------------------------------------------------
1428
# Test updating items that do not exist in the current WC rev, but do
1429
# exist at some future revision.
1431
def update_to_future_add(sbox):
1432
"update target that was added in a future rev"
1435
wc_dir = sbox.wc_dir
1437
# Update the entire WC to rev 0
1438
# Create expected output tree for an update to rev 0
1439
expected_output = svntest.wc.State(wc_dir, {
1440
'iota' : Item(status='D '),
1441
'A' : Item(status='D '),
1444
# Create expected disk tree for the update to rev 0
1445
expected_disk = svntest.wc.State(wc_dir, { })
1447
# Do the update and check the results.
1448
svntest.actions.run_and_verify_update(wc_dir,
1452
None, None, None, None, 0,
1455
# Update iota to the current HEAD.
1456
iota_path = os.path.join(wc_dir, 'iota')
1457
expected_output = svntest.wc.State(wc_dir, {
1458
'iota' : Item(status='A '),
1460
expected_disk = svntest.wc.State('', {
1461
'iota' : Item("This is the file 'iota'.")
1464
svntest.actions.run_and_verify_update(wc_dir,
1468
None, None, None, None, 0,
1471
# Now try updating the directory into the future
1472
A_path = os.path.join(wc_dir, 'A')
1474
expected_status = svntest.wc.State(wc_dir, {
1475
'A' : Item(status='A '),
1476
'A/mu' : Item(status='A '),
1477
'A/B' : Item(status='A '),
1478
'A/B/lambda' : Item(status='A '),
1479
'A/B/E' : Item(status='A '),
1480
'A/B/E/alpha' : Item(status='A '),
1481
'A/B/E/beta' : Item(status='A '),
1482
'A/B/F' : Item(status='A '),
1483
'A/C' : Item(status='A '),
1484
'A/D' : Item(status='A '),
1485
'A/D/gamma' : Item(status='A '),
1486
'A/D/G' : Item(status='A '),
1487
'A/D/G/pi' : Item(status='A '),
1488
'A/D/G/rho' : Item(status='A '),
1489
'A/D/G/tau' : Item(status='A '),
1490
'A/D/H' : Item(status='A '),
1491
'A/D/H/chi' : Item(status='A '),
1492
'A/D/H/psi' : Item(status='A '),
1493
'A/D/H/omega' : Item(status='A ')
1495
expected_disk = svntest.main.greek_state.copy()
1497
svntest.actions.run_and_verify_update(wc_dir,
1501
None, None, None, None, 0,
1504
#----------------------------------------------------------------------
1506
def nested_in_read_only(sbox):
1507
"update a nested wc in a read-only wc"
1510
wc_dir = sbox.wc_dir
1512
# Delete/commit a file
1513
alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
1514
svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
1515
expected_output = svntest.wc.State(wc_dir, {
1516
'A/B/E/alpha' : Item(verb='Deleting'),
1518
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1519
expected_status.tweak(wc_rev=1)
1520
expected_status.remove('A/B/E/alpha')
1521
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1522
expected_status, None,
1523
None, None, None, None, wc_dir)
1524
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
1525
expected_status.tweak(wc_rev=2)
1526
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1528
# Delete/commit a directory that used to contain the deleted file
1529
B_path = os.path.join(wc_dir, 'A', 'B')
1530
svntest.actions.run_and_verify_svn(None, None, [], 'rm', B_path)
1531
expected_output = svntest.wc.State(wc_dir, {
1532
'A/B' : Item(verb='Deleting'),
1534
expected_status.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/beta', 'A/B/F')
1535
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1536
expected_status, None,
1537
None, None, None, None, wc_dir)
1539
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
1540
expected_status.tweak(wc_rev=3)
1541
svntest.actions.run_and_verify_status(wc_dir, expected_status)
1543
# Replace the deleted directory with a new checkout of an old
1544
# version of the directory, this gives it a "plausible" URL that
1545
# could be part of the containing wc
1546
B_url = svntest.main.current_repo_url + '/A/B'
1547
svntest.actions.run_and_verify_svn(None, None, [],
1548
'checkout', '-r', '1', B_url + "@1",
1550
expected_status = svntest.wc.State(B_path, {
1558
expected_status.tweak(wc_rev=1, status=' ')
1559
svntest.actions.run_and_verify_status(B_path, expected_status)
1561
# Make enclosing wc read only
1562
os.chmod(os.path.join(wc_dir, 'A', svntest.main.get_admin_name()), 0555)
1565
# Update of nested wc should still work
1566
expected_output = svntest.wc.State(B_path, {
1567
'E/alpha' : Item(status='D '),
1569
expected_disk = wc.State('', {
1570
'lambda' : wc.StateItem("This is the file 'lambda'."),
1571
'E' : wc.StateItem(),
1572
'E/beta' : wc.StateItem("This is the file 'beta'."),
1573
'F' : wc.StateItem(),
1575
expected_status.remove('E/alpha')
1576
expected_status.tweak(wc_rev=2)
1577
svntest.actions.run_and_verify_update(B_path,
1581
None, None, None, None, None, 0,
1584
os.chmod(os.path.join(wc_dir, 'A', svntest.main.get_admin_name()), 0777)
1586
#----------------------------------------------------------------------
1588
def update_xml_unsafe_dir(sbox):
1589
"update dir with xml-unsafe name"
1592
wc_dir = sbox.wc_dir
1594
# Make a backup copy of the working copy
1595
wc_backup = sbox.add_wc_path('backup')
1596
svntest.actions.duplicate_dir(wc_dir, wc_backup)
1598
# Make a couple of local mods to files
1599
test_path = os.path.join(wc_dir, ' foo & bar')
1600
svntest.main.run_svn(None, 'mkdir', test_path)
1602
# Created expected output tree for 'svn ci'
1603
expected_output = wc.State(wc_dir, {
1604
' foo & bar' : Item(verb='Adding'),
1607
# Create expected status tree; all local revisions should be at 1,
1608
# but 'foo & bar' should be at revision 2.
1609
expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1610
expected_status.tweak(wc_rev=1)
1611
expected_status.add({
1612
' foo & bar' : Item(status=' ', wc_rev=2),
1616
svntest.actions.run_and_verify_commit (wc_dir, expected_output,
1617
expected_status, None,
1618
None, None, None, None, wc_dir)
1620
# chdir into the funky path, and update from there.
1621
was_cwd = os.getcwd()
1624
svntest.actions.run_and_verify_svn("Update failed", None, [], 'up')
1628
########################################################################
1632
# list all tests here, starting with None:
1635
update_binary_file_2,
1636
update_ignores_added,
1638
receive_overlapping_same_change,
1639
update_to_resolve_text_conflicts,
1640
update_delete_modified_files,
1641
update_after_add_rm_deleted,
1645
prop_update_on_scheduled_delete,
1646
update_receive_illegal_name,
1647
update_deleted_missing_dir,
1648
another_hudson_problem,
1649
update_deleted_targets,
1650
new_dir_with_spaces,
1651
non_recursive_update,
1654
update_deletion_inside_out,
1655
update_schedule_add_dir,
1656
update_to_future_add,
1657
nested_in_read_only,
1658
obstructed_update_alters_wc_props,
1659
update_xml_unsafe_dir,
1662
if __name__ == '__main__':
1663
svntest.main.run_tests(test_list)