3 # basic_tests.py: testing working-copy interactions with ra_local
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-2007 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
, stat
, re
, os
24 from svntest
import wc
27 Skip
= svntest
.testcase
.Skip
28 XFail
= svntest
.testcase
.XFail
31 ######################################################################
34 # Each test must return on success or raise on failure.
36 #----------------------------------------------------------------------
38 def basic_checkout(sbox
):
39 "basic checkout of a wc"
41 sbox
.build(read_only
= True)
44 # Checkout of a different URL into a working copy fails
45 A_url
= sbox
.repo_url
+ '/A'
46 svntest
.actions
.run_and_verify_svn("No error where some expected",
47 None, svntest
.verify
.AnyOutput
,
48 # "Obstructed update",
52 # Make some changes to the working copy
53 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
54 svntest
.main
.file_append(mu_path
, 'appended mu text')
55 lambda_path
= os
.path
.join(wc_dir
, 'A', 'B', 'lambda')
56 os
.remove(lambda_path
)
57 G_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
59 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', G_path
)
61 expected_output
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
62 expected_output
.tweak('A/mu', status
='M ')
63 expected_output
.tweak('A/B/lambda', status
='! ')
64 expected_output
.tweak('A/D/G',
67 'A/D/G/tau', status
='D ')
69 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
71 # Repeat checkout of original URL into working copy with modifications
74 svntest
.actions
.run_and_verify_svn("Repeat checkout failed", None, [],
78 # lambda is restored, modifications remain, deletes remain scheduled
79 # for deletion although files are restored to the filesystem
80 expected_output
.tweak('A/B/lambda', status
=' ')
81 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
83 #----------------------------------------------------------------------
85 def basic_status(sbox
):
86 "basic status command"
88 sbox
.build(read_only
= True)
91 # Created expected output tree for 'svn status'
92 output
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
94 svntest
.actions
.run_and_verify_status(wc_dir
, output
)
96 os
.chdir(os
.path
.join(wc_dir
, 'A'))
97 output
= svntest
.actions
.get_virginal_state("..", 1)
98 svntest
.actions
.run_and_verify_status("..", output
)
100 #----------------------------------------------------------------------
102 def basic_commit(sbox
):
103 "basic commit command"
108 # Make a couple of local mods to files
109 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
110 rho_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'rho')
111 svntest
.main
.file_append(mu_path
, 'appended mu text')
112 svntest
.main
.file_append(rho_path
, 'new appended text for rho')
114 # Created expected output tree for 'svn ci'
115 expected_output
= wc
.State(wc_dir
, {
116 'A/mu' : Item(verb
='Sending'),
117 'A/D/G/rho' : Item(verb
='Sending'),
120 # Create expected status tree; all local revisions should be at 1,
121 # but mu and rho should be at revision 2.
122 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
123 expected_status
.tweak('A/mu', 'A/D/G/rho', wc_rev
=2)
125 svntest
.actions
.run_and_verify_commit(wc_dir
,
132 #----------------------------------------------------------------------
134 def basic_update(sbox
):
135 "basic update command"
140 # Make a backup copy of the working copy
141 wc_backup
= sbox
.add_wc_path('backup')
142 svntest
.actions
.duplicate_dir(wc_dir
, wc_backup
)
144 # Make a couple of local mods to files
145 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
146 rho_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'rho')
147 svntest
.main
.file_append(mu_path
, 'appended mu text')
148 svntest
.main
.file_append(rho_path
, 'new appended text for rho')
150 # Created expected output tree for 'svn ci'
151 expected_output
= wc
.State(wc_dir
, {
152 'A/mu' : Item(verb
='Sending'),
153 'A/D/G/rho' : Item(verb
='Sending'),
156 # Create expected status tree; all local revisions should be at 1,
157 # but mu and rho should be at revision 2.
158 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
159 expected_status
.tweak('A/mu', 'A/D/G/rho', wc_rev
=2)
162 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
163 expected_status
, None, wc_dir
)
165 # Create expected output tree for an update of the wc_backup.
166 expected_output
= wc
.State(wc_backup
, {
167 'A/mu' : Item(status
='U '),
168 'A/D/G/rho' : Item(status
='U '),
171 # Create expected disk tree for the update.
172 expected_disk
= svntest
.main
.greek_state
.copy()
173 expected_disk
.tweak('A/mu',
174 contents
=expected_disk
.desc
['A/mu'].contents
175 + 'appended mu text')
176 expected_disk
.tweak('A/D/G/rho',
177 contents
=expected_disk
.desc
['A/D/G/rho'].contents
178 + 'new appended text for rho')
180 # Create expected status tree for the update.
181 expected_status
= svntest
.actions
.get_virginal_state(wc_backup
, 2)
183 # Do the update and check the results in three ways.
184 svntest
.actions
.run_and_verify_update(wc_backup
,
189 # Unversioned paths, those that are not immediate children of a versioned
190 # path, are skipped and do not raise an error
191 xx_path
= os
.path
.join(wc_dir
, 'xx', 'xx')
192 exit_code
, out
, err
= svntest
.actions
.run_and_verify_svn(
193 "update xx/xx", ["Skipped '"+xx_path
+"'\n"], [],
195 exit_code
, out
, err
= svntest
.actions
.run_and_verify_svn(
196 "update xx/xx", [], [],
197 'update', '--quiet', xx_path
)
199 # URL's are also skipped.
200 urls
= ('http://localhost/a/b/c', 'http://localhost', 'svn://localhost')
202 exit_code
, out
, err
= svntest
.actions
.run_and_verify_svn(
203 "update " + url
, ["Skipped '"+url
+"'\n"], [],
206 #----------------------------------------------------------------------
207 def basic_mkdir_url(sbox
):
212 Y_url
= sbox
.repo_url
+ '/Y'
213 Y_Z_url
= sbox
.repo_url
+ '/Y/Z'
215 svntest
.actions
.run_and_verify_svn("mkdir URL URL/subdir",
216 ["\n", "Committed revision 2.\n"], [],
217 'mkdir', '-m', 'log_msg', Y_url
, Y_Z_url
)
219 expected_output
= wc
.State(sbox
.wc_dir
, {
220 'Y' : Item(status
='A '),
221 'Y/Z' : Item(status
='A '),
223 expected_disk
= svntest
.main
.greek_state
.copy()
228 expected_status
= svntest
.actions
.get_virginal_state(sbox
.wc_dir
, 2)
229 expected_status
.add({
230 'Y' : Item(status
=' ', wc_rev
=2),
231 'Y/Z' : Item(status
=' ', wc_rev
=2)
234 svntest
.actions
.run_and_verify_update(sbox
.wc_dir
,
240 #----------------------------------------------------------------------
241 def basic_mkdir_url_with_parents(sbox
):
242 "basic mkdir URL, including parent directories"
246 X_Y_Z_url
= sbox
.repo_url
+ '/X/Y/Z'
247 X_Y_Z2_url
= sbox
.repo_url
+ '/X/Y/Z2'
248 X_T_C_url
= sbox
.repo_url
+ '/X/T/C'
249 U_V_url
= sbox
.repo_url
+ '/U/V'
250 svntest
.actions
.run_and_verify_svn("erroneous mkdir sans --parents",
252 ".*Try 'svn mkdir --parents' instead.*",
253 'mkdir', '-m', 'log_msg',
254 X_Y_Z_url
, X_Y_Z2_url
, X_T_C_url
, U_V_url
)
256 svntest
.actions
.run_and_verify_svn("mkdir --parents",
257 ["\n", "Committed revision 2.\n"], [],
258 'mkdir', '-m', 'log_msg', '--parents',
259 X_Y_Z_url
, X_Y_Z2_url
, X_T_C_url
, U_V_url
)
261 expected_output
= wc
.State(sbox
.wc_dir
, {
262 'X' : Item(status
='A '),
263 'X/Y' : Item(status
='A '),
264 'X/Y/Z' : Item(status
='A '),
265 'X/Y/Z2' : Item(status
='A '),
266 'X/T' : Item(status
='A '),
267 'X/T/C' : Item(status
='A '),
268 'U' : Item(status
='A '),
269 'U/V' : Item(status
='A '),
271 expected_disk
= svntest
.main
.greek_state
.copy()
282 expected_status
= svntest
.actions
.get_virginal_state(sbox
.wc_dir
, 2)
283 expected_status
.add({
284 'X' : Item(status
=' ', wc_rev
=2),
285 'X/Y' : Item(status
=' ', wc_rev
=2),
286 'X/Y/Z' : Item(status
=' ', wc_rev
=2),
287 'X/Y/Z2' : Item(status
=' ', wc_rev
=2),
288 'X/T' : Item(status
=' ', wc_rev
=2),
289 'X/T/C' : Item(status
=' ', wc_rev
=2),
290 'U' : Item(status
=' ', wc_rev
=2),
291 'U/V' : Item(status
=' ', wc_rev
=2),
293 svntest
.actions
.run_and_verify_update(sbox
.wc_dir
,
299 #----------------------------------------------------------------------
300 def basic_mkdir_wc_with_parents(sbox
):
301 "basic mkdir, including parent directories"
306 Y_Z_path
= os
.path
.join(wc_dir
, 'Y', 'Z')
308 svntest
.actions
.run_and_verify_svn("erroneous mkdir dir/subdir", [],
309 ".*Try 'svn mkdir --parents' instead.*",
312 svntest
.actions
.run_and_verify_svn("mkdir dir/subdir", None, [],
313 'mkdir', '--parents', Y_Z_path
)
316 #----------------------------------------------------------------------
317 def basic_corruption(sbox
):
318 "basic corruption detection"
320 ## I always wanted a test named "basic_corruption". :-)
321 ## Here's how it works:
323 ## 1. Make a working copy at rev 1, duplicate it. Now we have
324 ## two working copies at rev 1. Call them first and second.
325 ## 2. Make a local mod to `first/A/mu'.
326 ## 3. Intentionally corrupt `first/A/.svn/text-base/mu.svn-base'.
327 ## 4. Try to commit, expect a failure.
328 ## 5. Repair the text-base, commit again, expect success.
329 ## 6. Intentionally corrupt `second/A/.svn/text-base/mu.svn-base'.
330 ## 7. Try to update `second', expect failure.
331 ## 8. Repair the text-base, update again, expect success.
338 # Make the "other" working copy
339 other_wc
= sbox
.add_wc_path('other')
340 svntest
.actions
.duplicate_dir(wc_dir
, other_wc
)
342 # Make a local mod to mu
343 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
344 svntest
.main
.file_append(mu_path
, 'appended mu text')
346 # Created expected output tree for 'svn ci'
347 expected_output
= wc
.State(wc_dir
, {
348 'A/mu' : Item(verb
='Sending'),
351 # Create expected status tree; all local revisions should be at 1,
352 # but mu should be at revision 2.
353 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
354 expected_status
.tweak('A/mu', wc_rev
=2)
356 # Modify mu's text-base, so we get a checksum failure the first time
358 tb_dir_path
= os
.path
.join(wc_dir
, 'A',
359 svntest
.main
.get_admin_name(), 'text-base')
360 mu_tb_path
= os
.path
.join(tb_dir_path
, 'mu.svn-base')
361 mu_saved_tb_path
= mu_tb_path
+ "-saved"
362 tb_dir_saved_mode
= os
.stat(tb_dir_path
)[stat
.ST_MODE
]
363 mu_tb_saved_mode
= os
.stat(mu_tb_path
)[stat
.ST_MODE
]
364 os
.chmod(tb_dir_path
, 0777) # ### What's a more portable way to do this?
365 os
.chmod(mu_tb_path
, 0666) # ### Would rather not use hardcoded numbers.
366 shutil
.copyfile(mu_tb_path
, mu_saved_tb_path
)
367 svntest
.main
.file_append(mu_tb_path
, 'Aaagggkkk, corruption!')
368 os
.chmod(tb_dir_path
, tb_dir_saved_mode
)
369 os
.chmod(mu_tb_path
, mu_tb_saved_mode
)
371 # This commit should fail due to text base corruption.
372 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
373 expected_status
, "svn: Checksum",
376 # Restore the uncorrupted text base.
377 os
.chmod(tb_dir_path
, 0777)
378 os
.chmod(mu_tb_path
, 0666)
379 os
.remove(mu_tb_path
)
380 os
.rename(mu_saved_tb_path
, mu_tb_path
)
381 os
.chmod(tb_dir_path
, tb_dir_saved_mode
)
382 os
.chmod(mu_tb_path
, mu_tb_saved_mode
)
384 # This commit should succeed.
385 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
386 expected_status
, None, wc_dir
)
388 # Create expected output tree for an update of the other_wc.
389 expected_output
= wc
.State(other_wc
, {
390 'A/mu' : Item(status
='U '),
393 # Create expected disk tree for the update.
394 expected_disk
= svntest
.main
.greek_state
.copy()
395 expected_disk
.tweak('A/mu',
396 contents
=expected_disk
.desc
['A/mu'].contents
397 + 'appended mu text')
399 # Create expected status tree for the update.
400 expected_status
= svntest
.actions
.get_virginal_state(other_wc
, 2)
402 # Modify mu's text-base, so we get a checksum failure the first time
404 tb_dir_path
= os
.path
.join(other_wc
, 'A',
405 svntest
.main
.get_admin_name(), 'text-base')
406 mu_tb_path
= os
.path
.join(tb_dir_path
, 'mu.svn-base')
407 mu_saved_tb_path
= mu_tb_path
+ "-saved"
408 tb_dir_saved_mode
= os
.stat(tb_dir_path
)[stat
.ST_MODE
]
409 mu_tb_saved_mode
= os
.stat(mu_tb_path
)[stat
.ST_MODE
]
410 os
.chmod(tb_dir_path
, 0777)
411 os
.chmod(mu_tb_path
, 0666)
412 shutil
.copyfile(mu_tb_path
, mu_saved_tb_path
)
413 svntest
.main
.file_append(mu_tb_path
, 'Aiyeeeee, corruption!\nHelp!\n')
414 os
.chmod(tb_dir_path
, tb_dir_saved_mode
)
415 os
.chmod(mu_tb_path
, mu_tb_saved_mode
)
417 # Do the update and check the results in three ways.
418 svntest
.actions
.run_and_verify_update(other_wc
,
422 "svn: Checksum", other_wc
)
424 # Restore the uncorrupted text base.
425 os
.chmod(tb_dir_path
, 0777)
426 os
.chmod(mu_tb_path
, 0666)
427 os
.remove(mu_tb_path
)
428 os
.rename(mu_saved_tb_path
, mu_tb_path
)
429 os
.chmod(tb_dir_path
, tb_dir_saved_mode
)
430 os
.chmod(mu_tb_path
, mu_tb_saved_mode
)
432 # This update should succeed. (Actually, I'm kind of astonished
433 # that this works without even an intervening "svn cleanup".)
434 svntest
.actions
.run_and_verify_update(other_wc
,
439 #----------------------------------------------------------------------
440 def basic_merging_update(sbox
):
441 "receiving text merges as part of an update"
446 # First change the greek tree to make two files 10 lines long
447 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
448 rho_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'rho')
451 for x
in range(2,11):
452 mu_text
= mu_text
+ '\nThis is line ' + `x`
+ ' in mu'
453 rho_text
= rho_text
+ '\nThis is line ' + `x`
+ ' in rho'
454 svntest
.main
.file_append(mu_path
, mu_text
)
455 svntest
.main
.file_append(rho_path
, rho_text
)
457 # Create expected output tree for initial commit
458 expected_output
= wc
.State(wc_dir
, {
459 'A/mu' : Item(verb
='Sending'),
460 'A/D/G/rho' : Item(verb
='Sending'),
463 # Create expected status tree; all local revisions should be at 1,
464 # but mu and rho should be at revision 2.
465 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
466 expected_status
.tweak('A/mu', 'A/D/G/rho', wc_rev
=2)
469 svntest
.actions
.run_and_verify_commit(wc_dir
,
475 # Make a backup copy of the working copy
476 wc_backup
= sbox
.add_wc_path('backup')
477 svntest
.actions
.duplicate_dir(wc_dir
, wc_backup
)
479 # Make a couple of local mods to files
480 svntest
.main
.file_append(mu_path
, ' Appended to line 10 of mu')
481 svntest
.main
.file_append(rho_path
, ' Appended to line 10 of rho')
483 # Created expected output tree for 'svn ci'
484 expected_output
= wc
.State(wc_dir
, {
485 'A/mu' : Item(verb
='Sending'),
486 'A/D/G/rho' : Item(verb
='Sending'),
489 # Create expected status tree; all local revisions should be at 1,
490 # but mu and rho should be at revision 3.
491 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
492 expected_status
.tweak('A/mu', 'A/D/G/rho', wc_rev
=3)
495 svntest
.actions
.run_and_verify_commit(wc_dir
,
501 # Make local mods to wc_backup by recreating mu and rho
502 mu_path_backup
= os
.path
.join(wc_backup
, 'A', 'mu')
503 rho_path_backup
= os
.path
.join(wc_backup
, 'A', 'D', 'G', 'rho')
505 # open in 'truncate to zero then write" mode
506 backup_mu_text
= 'This is the new line 1 in the backup copy of mu'
507 for x
in range(2,11):
508 backup_mu_text
= backup_mu_text
+ '\nThis is line ' + `x`
+ ' in mu'
509 svntest
.main
.file_write(mu_path_backup
, backup_mu_text
, 'w+')
511 backup_rho_text
= 'This is the new line 1 in the backup copy of rho'
512 for x
in range(2,11):
513 backup_rho_text
= backup_rho_text
+ '\nThis is line ' + `x`
+ ' in rho'
514 svntest
.main
.file_write(rho_path_backup
, backup_rho_text
, 'w+')
516 # Create expected output tree for an update of the wc_backup.
517 expected_output
= wc
.State(wc_backup
, {
518 'A/mu' : Item(status
='G '),
519 'A/D/G/rho' : Item(status
='G '),
522 # Create expected disk tree for the update.
523 expected_disk
= svntest
.main
.greek_state
.copy()
524 expected_disk
.tweak('A/mu',
525 contents
=backup_mu_text
+ ' Appended to line 10 of mu')
526 expected_disk
.tweak('A/D/G/rho',
527 contents
=backup_rho_text
+ ' Appended to line 10 of rho')
529 # Create expected status tree for the update.
530 expected_status
= svntest
.actions
.get_virginal_state(wc_backup
, 3)
531 expected_status
.tweak('A/mu', 'A/D/G/rho', status
='M ')
533 # Do the update and check the results in three ways.
534 svntest
.actions
.run_and_verify_update(wc_backup
,
539 #----------------------------------------------------------------------
542 def basic_conflict(sbox
):
543 "basic conflict creation and resolution"
548 # Make a backup copy of the working copy
549 wc_backup
= sbox
.add_wc_path('backup')
550 svntest
.actions
.duplicate_dir(wc_dir
, wc_backup
)
552 # Make a couple of local mods to files which will be committed
553 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
554 rho_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'rho')
555 svntest
.main
.file_append(mu_path
, 'Original appended text for mu\n')
556 svntest
.main
.file_append(rho_path
, 'Original appended text for rho\n')
558 # Make a couple of local mods to files which will be conflicted
559 mu_path_backup
= os
.path
.join(wc_backup
, 'A', 'mu')
560 rho_path_backup
= os
.path
.join(wc_backup
, 'A', 'D', 'G', 'rho')
561 svntest
.main
.file_append(mu_path_backup
,
562 'Conflicting appended text for mu\n')
563 svntest
.main
.file_append(rho_path_backup
,
564 'Conflicting appended text for rho\n')
566 # Created expected output tree for 'svn ci'
567 expected_output
= wc
.State(wc_dir
, {
568 'A/mu' : Item(verb
='Sending'),
569 'A/D/G/rho' : Item(verb
='Sending'),
572 # Create expected status tree; all local revisions should be at 1,
573 # but mu and rho should be at revision 2.
574 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
575 expected_status
.tweak('A/mu', 'A/D/G/rho', wc_rev
=2)
578 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
579 expected_status
, None, wc_dir
)
581 # Create expected output tree for an update of the wc_backup.
582 expected_output
= wc
.State(wc_backup
, {
583 'A/mu' : Item(status
='C '),
584 'A/D/G/rho' : Item(status
='C '),
587 # Create expected disk tree for the update.
588 expected_disk
= svntest
.main
.greek_state
.copy()
589 expected_disk
.tweak('A/mu',
590 contents
="\n".join(["This is the file 'mu'.",
592 "Conflicting appended text for mu",
594 "Original appended text for mu",
597 expected_disk
.tweak('A/D/G/rho',
598 contents
="\n".join(["This is the file 'rho'.",
600 "Conflicting appended text for rho",
602 "Original appended text for rho",
606 # Create expected status tree for the update.
607 expected_status
= svntest
.actions
.get_virginal_state(wc_backup
, '2')
608 expected_status
.tweak('A/mu', 'A/D/G/rho', status
='C ')
610 # "Extra" files that we expect to result from the conflicts.
611 # These are expressed as list of regexps. What a cool system! :-)
612 extra_files
= ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine',
613 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine',]
615 # Do the update and check the results in three ways.
616 # All "extra" files are passed to detect_conflict_files().
617 svntest
.actions
.run_and_verify_update(wc_backup
,
622 svntest
.tree
.detect_conflict_files
,
625 # verify that the extra_files list is now empty.
626 if len(extra_files
) != 0:
627 # Because we want to be a well-behaved test, we silently raise if
628 # the test fails. However, these two print statements would
629 # probably reveal the cause for the failure, if they were
632 # print "Not all extra reject files have been accounted for:"
634 ### we should raise a less generic error here. which?
635 raise svntest
.Failure
637 # So now mu and rho are both in a "conflicted" state. Run 'svn
640 svntest
.actions
.run_and_verify_svn("Resolved command", None, [],
645 # See if they've changed back to plain old 'M' state.
646 expected_status
.tweak('A/mu', 'A/D/G/rho', status
='M ')
648 # There should be *no* extra backup files lying around the working
649 # copy after resolving the conflict; thus we're not passing a custom
651 svntest
.actions
.run_and_verify_status(wc_backup
, expected_status
)
654 #----------------------------------------------------------------------
656 def basic_cleanup(sbox
):
657 "basic cleanup command"
659 sbox
.build(read_only
= True)
662 # Lock some directories.
663 B_path
= os
.path
.join(wc_dir
, 'A', 'B')
664 G_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
665 C_path
= os
.path
.join(wc_dir
, 'A', 'C')
666 svntest
.actions
.lock_admin_dir(B_path
)
667 svntest
.actions
.lock_admin_dir(G_path
)
668 svntest
.actions
.lock_admin_dir(C_path
)
670 # Verify locked status.
671 expected_output
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
672 expected_output
.tweak('A/B', 'A/D/G', 'A/C', locked
='L')
674 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
676 # corrupted/non-existing temporary directory should be restored
677 svntest
.actions
.remove_admin_tmp_dir(B_path
)
679 # Run cleanup (### todo: cleanup doesn't currently print anything)
680 svntest
.actions
.run_and_verify_svn("Cleanup command", None, [],
683 # Verify unlocked status.
684 expected_output
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
686 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
689 #----------------------------------------------------------------------
691 def basic_revert(sbox
):
692 "basic revert command"
697 # Modify some files and props.
698 beta_path
= os
.path
.join(wc_dir
, 'A', 'B', 'E', 'beta')
699 gamma_path
= os
.path
.join(wc_dir
, 'A', 'D', 'gamma')
700 iota_path
= os
.path
.join(wc_dir
, 'iota')
701 rho_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'rho')
702 zeta_path
= os
.path
.join(wc_dir
, 'A', 'D', 'H', 'zeta')
703 svntest
.main
.file_append(beta_path
, "Added some text to 'beta'.\n")
704 svntest
.main
.file_append(iota_path
, "Added some text to 'iota'.\n")
705 svntest
.main
.file_append(rho_path
, "Added some text to 'rho'.\n")
706 svntest
.main
.file_append(zeta_path
, "Added some text to 'zeta'.\n")
708 svntest
.actions
.run_and_verify_svn("Add command", None, [],
710 svntest
.actions
.run_and_verify_svn("Add prop command", None, [],
711 'ps', 'random-prop', 'propvalue',
713 svntest
.actions
.run_and_verify_svn("Add prop command", None, [],
714 'ps', 'random-prop', 'propvalue',
717 # Verify modified status.
718 expected_output
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
719 expected_output
.tweak('A/B/E/beta', 'A/D/G/rho', status
='M ')
720 expected_output
.tweak('iota', status
='MM')
721 expected_output
.tweak('A/D/gamma', status
=' M')
722 expected_output
.add({
723 'A/D/H/zeta' : Item(status
='A ', wc_rev
=0),
726 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
728 # Run revert (### todo: revert doesn't currently print anything)
729 svntest
.actions
.run_and_verify_svn("Revert command", None, [],
732 svntest
.actions
.run_and_verify_svn("Revert command", None, [],
733 'revert', gamma_path
)
735 svntest
.actions
.run_and_verify_svn("Revert command", None, [],
738 svntest
.actions
.run_and_verify_svn("Revert command", None, [],
741 svntest
.actions
.run_and_verify_svn("Revert command", None, [],
744 # Verify unmodified status.
745 expected_output
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
747 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
749 # Now, really make sure the contents are back to their original state.
750 fp
= open(beta_path
, 'r')
751 lines
= fp
.readlines()
752 if not ((len (lines
) == 1) and (lines
[0] == "This is the file 'beta'.\n")):
753 print "Revert failed to restore original text."
754 raise svntest
.Failure
755 fp
= open(iota_path
, 'r')
756 lines
= fp
.readlines()
757 if not ((len (lines
) == 1) and (lines
[0] == "This is the file 'iota'.\n")):
758 print "Revert failed to restore original text."
759 raise svntest
.Failure
760 fp
= open(rho_path
, 'r')
761 lines
= fp
.readlines()
762 if not ((len (lines
) == 1) and (lines
[0] == "This is the file 'rho'.\n")):
763 print "Revert failed to restore original text."
764 raise svntest
.Failure
765 fp
= open(zeta_path
, 'r')
766 lines
= fp
.readlines()
767 if not ((len (lines
) == 1) and (lines
[0] == "Added some text to 'zeta'.\n")):
768 ### we should raise a less generic error here. which?
769 raise svntest
.Failure
771 # Finally, check that reverted file is not readonly
773 svntest
.actions
.run_and_verify_svn(None, None, [], 'revert', beta_path
)
774 if not (open(beta_path
, 'rw+')):
775 raise svntest
.Failure
777 # Check that a directory scheduled to be added, but physically
778 # removed, can be reverted.
779 X_path
= os
.path
.join(wc_dir
, 'X')
781 svntest
.actions
.run_and_verify_svn(None, None, [], 'mkdir', X_path
)
783 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
784 expected_status
.add({
785 'X' : Item(status
='A ', wc_rev
=0),
787 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
788 svntest
.main
.safe_rmtree(X_path
)
790 svntest
.actions
.run_and_verify_svn(None, None, [], 'revert', X_path
)
792 expected_status
.remove('X')
793 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
795 # Check that a directory scheduled for deletion, but physically
796 # removed, can be reverted.
797 E_path
= os
.path
.join(wc_dir
, 'A', 'B', 'E')
798 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
800 ### Most of the rest of this test is ineffective, due to the
801 ### problems described in issue #1611.
802 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', E_path
)
803 svntest
.main
.safe_rmtree(E_path
)
804 expected_status
.tweak('A/B/E', status
='D ')
805 expected_status
.tweak('A/B/E', wc_rev
='?')
806 ### FIXME: A weakness in the test framework, described in detail
807 ### in issue #1611, prevents us from checking via status. Grr.
809 # svntest.actions.run_and_verify_status(wc_dir, expected_status,
810 # None, None, None, None)
813 ### If you were to uncomment the above, you'd get an error like so:
815 # =============================================================
816 # Expected E and actual E are different!
817 # =============================================================
818 # EXPECTED NODE TO BE:
819 # =============================================================
821 # Path: working_copies/basic_tests-10/A/B/E
824 # Attributes: {'status': 'D ', 'wc_rev': '?'}
826 # =============================================================
828 # =============================================================
830 # Path: working_copies/basic_tests-10/A/B/E
833 # Attributes: {'status': 'D ', 'wc_rev': '?'}
834 # Children: is a file.
835 # Unequal Types: one Node is a file, the other is a directory
837 # This will actually print
839 # "Failed to revert 'working_copies/basic_tests-10/A/B/E' -- \
840 # try updating instead."
842 # ...but due to test suite lossage, it'll still look like success.
843 svntest
.actions
.run_and_verify_svn(None, None, [], 'revert', E_path
)
845 ### FIXME: Again, the problem described in issue #1611 bites us here.
847 # expected_status.tweak('A/B/E', status=' ')
848 # svntest.actions.run_and_verify_status(wc_dir, expected_status,
849 # None, None, None, None)
852 #----------------------------------------------------------------------
854 def basic_switch(sbox
):
855 "basic switch command"
857 sbox
.build(read_only
= True)
860 ### Switch the file `iota' to `A/D/gamma'.
862 # Construct some paths for convenience
863 iota_path
= os
.path
.join(wc_dir
, 'iota')
864 gamma_url
= sbox
.repo_url
+ '/A/D/gamma'
866 # Create expected output tree
867 expected_output
= wc
.State(wc_dir
, {
868 'iota' : Item(status
='U '),
871 # Create expected disk tree (iota will have gamma's contents)
872 expected_disk
= svntest
.main
.greek_state
.copy()
873 expected_disk
.tweak('iota',
874 contents
=expected_disk
.desc
['A/D/gamma'].contents
)
876 # Create expected status tree
877 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
878 expected_status
.tweak('iota', switched
='S')
880 # Do the switch and check the results in three ways.
881 svntest
.actions
.run_and_verify_switch(wc_dir
, iota_path
, gamma_url
,
886 ### Switch the directory `A/D/H' to `A/D/G'.
888 # Construct some paths for convenience
889 ADH_path
= os
.path
.join(wc_dir
, 'A', 'D', 'H')
890 chi_path
= os
.path
.join(ADH_path
, 'chi')
891 omega_path
= os
.path
.join(ADH_path
, 'omega')
892 psi_path
= os
.path
.join(ADH_path
, 'psi')
893 pi_path
= os
.path
.join(ADH_path
, 'pi')
894 tau_path
= os
.path
.join(ADH_path
, 'tau')
895 rho_path
= os
.path
.join(ADH_path
, 'rho')
896 ADG_url
= sbox
.repo_url
+ '/A/D/G'
898 # Create expected output tree
899 expected_output
= wc
.State(wc_dir
, {
900 'A/D/H/chi' : Item(status
='D '),
901 'A/D/H/omega' : Item(status
='D '),
902 'A/D/H/psi' : Item(status
='D '),
903 'A/D/H/pi' : Item(status
='A '),
904 'A/D/H/rho' : Item(status
='A '),
905 'A/D/H/tau' : Item(status
='A '),
908 # Create expected disk tree (iota will have gamma's contents,
909 # A/D/H/* will look like A/D/G/*)
910 expected_disk
= svntest
.main
.greek_state
.copy()
911 expected_disk
.tweak('iota',
912 contents
=expected_disk
.desc
['A/D/gamma'].contents
)
913 expected_disk
.remove('A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi')
915 'A/D/H/pi' : Item("This is the file 'pi'.\n"),
916 'A/D/H/rho' : Item("This is the file 'rho'.\n"),
917 'A/D/H/tau' : Item("This is the file 'tau'.\n"),
920 # Create expected status
921 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
922 expected_status
.remove('A/D/H/chi',
925 expected_status
.add({
926 'A/D/H/pi' : Item(status
=' ', wc_rev
=1),
927 'A/D/H/rho' : Item(status
=' ', wc_rev
=1),
928 'A/D/H/tau' : Item(status
=' ', wc_rev
=1),
930 expected_status
.tweak('iota', 'A/D/H', switched
='S')
932 # Do the switch and check the results in three ways.
933 svntest
.actions
.run_and_verify_switch(wc_dir
, ADH_path
, ADG_url
,
938 #----------------------------------------------------------------------
940 def verify_file_deleted(message
, path
):
945 if message
is not None:
947 ###TODO We should raise a less generic error here. which?
950 def verify_dir_deleted(path
):
951 if not os
.path
.isdir(path
):
956 def basic_delete(sbox
):
957 "basic delete command"
963 chi_parent_path
= os
.path
.join(wc_dir
, 'A', 'D', 'H')
964 chi_path
= os
.path
.join(chi_parent_path
, 'chi')
965 svntest
.main
.file_append(chi_path
, 'added to chi')
967 # modify props of rho (file)
968 rho_parent_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
969 rho_path
= os
.path
.join(rho_parent_path
, 'rho')
970 svntest
.main
.run_svn(None, 'ps', 'abc', 'def', rho_path
)
972 # modify props of F (dir)
973 F_parent_path
= os
.path
.join(wc_dir
, 'A', 'B')
974 F_path
= os
.path
.join(F_parent_path
, 'F')
975 svntest
.main
.run_svn(None, 'ps', 'abc', 'def', F_path
)
978 sigma_parent_path
= os
.path
.join(wc_dir
, 'A', 'C')
979 sigma_path
= os
.path
.join(sigma_parent_path
, 'sigma')
980 svntest
.main
.file_append(sigma_path
, 'unversioned sigma')
982 # unversioned directory
983 Q_parent_path
= sigma_parent_path
984 Q_path
= os
.path
.join(Q_parent_path
, 'Q')
987 # added directory hierarchies
988 X_parent_path
= os
.path
.join(wc_dir
, 'A', 'B')
989 X_path
= os
.path
.join(X_parent_path
, 'X')
990 svntest
.main
.run_svn(None, 'mkdir', X_path
)
991 X_child_path
= os
.path
.join(X_path
, 'xi')
992 svntest
.main
.file_append(X_child_path
, 'added xi')
993 svntest
.main
.run_svn(None, 'add', X_child_path
)
994 Y_parent_path
= os
.path
.join(wc_dir
, 'A', 'D')
995 Y_path
= os
.path
.join(Y_parent_path
, 'Y')
996 svntest
.main
.run_svn(None, 'mkdir', Y_path
)
999 expected_output
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1000 expected_output
.tweak('A/D/H/chi', status
='M ')
1001 expected_output
.tweak('A/D/G/rho', 'A/B/F', status
=' M')
1002 # expected_output.tweak('A/C/sigma', status='? ')
1003 expected_output
.add({
1004 'A/B/X' : Item(status
='A ', wc_rev
=0),
1005 'A/B/X/xi' : Item(status
='A ', wc_rev
=0),
1006 'A/D/Y' : Item(status
='A ', wc_rev
=0),
1009 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
1011 # 'svn rm' that should fail
1012 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1015 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1016 'rm', chi_parent_path
)
1018 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1021 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1022 'rm', rho_parent_path
)
1024 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1027 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1028 'rm', F_parent_path
)
1030 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1033 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1034 'rm', sigma_parent_path
)
1036 svntest
.actions
.run_and_verify_svn(None, None, svntest
.verify
.AnyOutput
,
1039 # check status has not changed
1040 svntest
.actions
.run_and_verify_status(wc_dir
, expected_output
)
1042 # 'svn rm' that should work
1043 E_path
= os
.path
.join(wc_dir
, 'A', 'B', 'E')
1044 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', E_path
)
1046 # 'svn rm --force' that should work
1047 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', '--force',
1050 svntest
.actions
.run_and_verify_svn(None, None, [],
1051 'rm', '--force', rho_parent_path
)
1053 svntest
.actions
.run_and_verify_svn(None, None, [],
1054 'rm', '--force', F_path
)
1056 svntest
.actions
.run_and_verify_svn(None, None, [],
1057 'rm', '--force', sigma_parent_path
)
1059 svntest
.actions
.run_and_verify_svn(None, None, [],
1060 'rm', '--force', X_path
)
1062 # Deleting already removed from wc versioned item with --force
1063 iota_path
= os
.path
.join(wc_dir
, 'iota')
1064 os
.remove(iota_path
)
1065 svntest
.actions
.run_and_verify_svn(None, None, [],
1066 'rm', '--force', iota_path
)
1068 # and without --force
1069 gamma_path
= os
.path
.join(wc_dir
, 'A', 'D', 'gamma')
1070 os
.remove(gamma_path
)
1071 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', gamma_path
)
1073 # Deleting already scheduled for deletion doesn't require --force
1074 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', gamma_path
)
1076 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', E_path
)
1079 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1080 expected_status
.tweak('A/D/H',
1094 'A/D/gamma', status
='D ')
1095 expected_status
.add({
1096 'A/D/Y' : Item(status
='A ', wc_rev
=0),
1099 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
1101 # issue 687 delete directory with uncommitted directory child
1102 svntest
.actions
.run_and_verify_svn(None, None, [],
1103 'rm', '--force', Y_parent_path
)
1105 expected_status
.tweak('A/D', status
='D ')
1106 expected_status
.remove('A/D/Y')
1107 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
1109 # check files have been removed
1110 verify_file_deleted("Failed to remove text modified file", rho_path
)
1111 verify_file_deleted("Failed to remove prop modified file", chi_path
)
1112 verify_file_deleted("Failed to remove unversioned file", sigma_path
)
1113 verify_file_deleted("Failed to remove unmodified file",
1114 os
.path
.join(E_path
, 'alpha'))
1116 # check versioned dir is not removed
1117 if not verify_dir_deleted(F_path
):
1118 print "Removed versioned dir"
1119 ### we should raise a less generic error here. which?
1120 raise svntest
.Failure
1122 # check unversioned and added dirs has been removed
1123 if verify_dir_deleted(Q_path
):
1124 print "Failed to remove unversioned dir"
1125 ### we should raise a less generic error here. which?
1126 raise svntest
.Failure
1127 if verify_dir_deleted(X_path
):
1128 print "Failed to remove added dir"
1129 ### we should raise a less generic error here. which?
1130 raise svntest
.Failure
1132 # Deleting unversioned file explicitly
1133 foo_path
= os
.path
.join(wc_dir
, 'foo')
1134 svntest
.main
.file_append(foo_path
, 'unversioned foo')
1135 svntest
.actions
.run_and_verify_svn(None, None, [],
1136 'rm', '--force', foo_path
)
1137 verify_file_deleted("Failed to remove unversioned file foo", foo_path
)
1139 # At one stage deleting an URL dumped core
1140 iota_URL
= sbox
.repo_url
+ '/iota'
1142 svntest
.actions
.run_and_verify_svn(None,
1143 ["\n", "Committed revision 2.\n"], [],
1144 'rm', '-m', 'delete iota URL',
1147 #----------------------------------------------------------------------
1149 def basic_checkout_deleted(sbox
):
1150 "checkout a path no longer in HEAD"
1153 wc_dir
= sbox
.wc_dir
1155 # Delete A/D and commit.
1156 D_path
= os
.path
.join(wc_dir
, 'A', 'D')
1157 svntest
.actions
.run_and_verify_svn("error scheduling A/D for deletion",
1158 None, [], 'rm', '--force', D_path
)
1160 expected_output
= wc
.State(wc_dir
, {
1161 'A/D' : Item(verb
='Deleting'),
1164 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1165 expected_status
.remove('A/D', 'A/D/G', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau',
1166 'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega',
1169 svntest
.actions
.run_and_verify_commit(wc_dir
,
1170 expected_output
, expected_status
,
1173 # Now try to checkout revision 1 of A/D.
1174 url
= sbox
.repo_url
+ '/A/D'
1175 wc2
= os
.path
.join(sbox
.wc_dir
, 'new_D')
1176 svntest
.actions
.run_and_verify_svn("error checking out r1 of A/D",
1177 None, [], 'co', '-r', '1',
1180 #----------------------------------------------------------------------
1182 # Issue 846, changing a deleted file to an added directory is not
1185 def basic_node_kind_change(sbox
):
1186 "attempt to change node kind"
1189 wc_dir
= sbox
.wc_dir
1191 # Schedule a file for deletion
1192 gamma_path
= os
.path
.join(wc_dir
, 'A', 'D', 'gamma')
1193 svntest
.main
.run_svn(None, 'rm', gamma_path
)
1195 # Status shows deleted file
1196 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1197 expected_status
.tweak('A/D/gamma', status
='D ')
1198 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
1200 # Try and fail to create a directory (file scheduled for deletion)
1201 svntest
.actions
.run_and_verify_svn('Cannot change node kind',
1202 None, svntest
.verify
.AnyOutput
,
1203 'mkdir', gamma_path
)
1205 # Status is unchanged
1206 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
1208 # Commit file deletion
1209 expected_output
= wc
.State(wc_dir
, {
1210 'A/D/gamma' : Item(verb
='Deleting'),
1212 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1213 expected_status
.remove('A/D/gamma')
1214 svntest
.actions
.run_and_verify_commit(wc_dir
,
1215 expected_output
, expected_status
,
1218 # Try and fail to create a directory (file deleted)
1219 svntest
.actions
.run_and_verify_svn('Cannot change node kind',
1220 None, svntest
.verify
.AnyOutput
,
1221 'mkdir', gamma_path
)
1223 # Status is unchanged
1224 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
1226 # Update to finally get rid of file
1227 svntest
.actions
.run_and_verify_svn(None, None, [], 'up', wc_dir
)
1229 # mkdir should succeed
1230 svntest
.actions
.run_and_verify_svn(None, None, [], 'mkdir', gamma_path
)
1232 expected_status
.tweak(wc_rev
=2)
1233 expected_status
.add({
1234 'A/D/gamma' : Item(status
='A ', wc_rev
=0),
1236 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
1238 #----------------------------------------------------------------------
1240 def basic_import(sbox
):
1241 "basic import of single new file"
1244 wc_dir
= sbox
.wc_dir
1246 # create a new directory with files of various permissions
1247 new_path
= os
.path
.join(wc_dir
, 'new_file')
1249 svntest
.main
.file_append(new_path
, "some text")
1251 # import new files into repository
1252 url
= sbox
.repo_url
+ "/dirA/dirB/new_file"
1253 exit_code
, output
, errput
= svntest
.actions
.run_and_verify_svn(
1254 'Cannot change node kind', None, [], 'import',
1255 '-m', 'Log message for new import', new_path
, url
)
1257 lastline
= output
.pop().strip()
1258 cm
= re
.compile("(Committed|Imported) revision [0-9]+.")
1259 match
= cm
.search(lastline
)
1261 ### we should raise a less generic error here. which?
1262 raise svntest
.Failure
1264 # remove (uncontrolled) local file
1267 # Create expected disk tree for the update (disregarding props)
1268 expected_disk
= svntest
.main
.greek_state
.copy()
1270 'dirA/dirB/new_file' : Item('some text'),
1273 # Create expected status tree for the update (disregarding props).
1274 # Newly imported file should be at revision 2.
1275 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 2)
1276 expected_status
.add({
1277 'dirA' : Item(status
=' ', wc_rev
=2),
1278 'dirA/dirB' : Item(status
=' ', wc_rev
=2),
1279 'dirA/dirB/new_file' : Item(status
=' ', wc_rev
=2),
1282 # Create expected output tree for the update.
1283 expected_output
= svntest
.wc
.State(wc_dir
, {
1284 'dirA' : Item(status
='A '),
1285 'dirA/dirB' : Item(status
='A '),
1286 'dirA/dirB/new_file' : Item(status
='A '),
1289 # do update and check three ways
1290 svntest
.actions
.run_and_verify_update(wc_dir
,
1297 #----------------------------------------------------------------------
1299 def basic_cat(sbox
):
1300 "basic cat of files"
1302 sbox
.build(read_only
= True)
1303 wc_dir
= sbox
.wc_dir
1305 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
1307 # Get repository text even if wc is modified
1308 svntest
.main
.file_append(mu_path
, "some text")
1309 svntest
.actions
.run_and_verify_svn(None, ["This is the file 'mu'.\n"],
1311 ###TODO is user/pass really necessary?
1315 #----------------------------------------------------------------------
1320 sbox
.build(read_only
= True)
1321 wc_dir
= sbox
.wc_dir
1323 # Even on Windows, the output will use forward slashes, so that's
1324 # what we expect below.
1328 svntest
.actions
.run_and_verify_svn("ls implicit current directory",
1333 svntest
.actions
.run_and_verify_svn('ls the root of working copy',
1338 svntest
.actions
.run_and_verify_svn('ls a working copy directory',
1339 ['B/\n', 'C/\n', 'D/\n', 'mu\n'],
1341 os
.path
.join(wc_dir
, 'A'))
1343 svntest
.actions
.run_and_verify_svn('ls working copy directory with -r BASE',
1344 ['B/\n', 'C/\n', 'D/\n', 'mu\n'],
1345 [], 'ls', '-r', 'BASE',
1346 os
.path
.join(wc_dir
, 'A'))
1348 svntest
.actions
.run_and_verify_svn('ls a single file',
1351 os
.path
.join(wc_dir
, 'A', 'mu'))
1353 svntest
.actions
.run_and_verify_svn('recursive ls',
1354 ['E/\n', 'E/alpha\n', 'E/beta\n', 'F/\n',
1355 'lambda\n' ], [], 'ls', '-R',
1356 os
.path
.join(wc_dir
, 'A', 'B'))
1359 #----------------------------------------------------------------------
1360 def nonexistent_repository(sbox
):
1361 "'svn log file:///nonexistent_path' should fail"
1365 # $ svn log file:///nonexistent_path
1367 # would go into an infinite loop, instead of failing immediately as
1368 # it should. The loop was because svn_ra_local__split_URL() used
1369 # svn_path_split() to lop off components and look for a repository
1370 # in each shorter path in turn, depending on svn_path_is_empty()
1371 # to test if it had reached the end. Somewhere along the line we
1372 # changed the path functions (perhaps revision 3113?), and
1373 # svn_path_split() stopped cooperating with svn_path_is_empty() in
1374 # this particular context -- svn_path_split() would reach "/",
1375 # svn_path_is_empty() would correctly claim that "/" is not empty,
1376 # the next svn_path_split() would return "/" again, and so on,
1379 # This bug was fixed in revision 3150, by checking for "/"
1380 # explicitly in svn_ra_local__split_URL(). By the time you read
1381 # this, that may or may not be the settled fix, however, so check
1382 # the logs to see if anything happened later.
1384 # Anyway: this test _always_ operates on a file:/// path. Note that
1385 # if someone runs this test on a system with "/nonexistent_path" in
1386 # the root directory, the test could fail, and that's just too bad :-).
1388 exit_code
, output
, errput
= svntest
.actions
.run_and_verify_svn(
1389 None, None, svntest
.verify
.AnyOutput
,
1390 'log', 'file:///nonexistent_path')
1393 if re
.match(".*Unable to open an ra_local session to URL.*", line
):
1396 # Else never matched the expected error output, so the test failed.
1397 raise svntest
.main
.SVNUnmatchedError
1400 #----------------------------------------------------------------------
1401 # Issue 1064. This test is only useful if running over a non-local RA
1402 # with authentication enabled, otherwise it will pass trivially.
1403 def basic_auth_cache(sbox
):
1404 "basic auth caching"
1406 sbox
.build(create_wc
= False, read_only
= True)
1407 wc_dir
= sbox
.wc_dir
1409 repo_dir
= sbox
.repo_dir
1410 repo_url
= sbox
.repo_url
1412 # Create a working copy without auth tokens
1413 svntest
.main
.safe_rmtree(wc_dir
)
1416 svntest
.actions
.run_and_verify_svn(None, None, [],
1420 # Failed with "not locked" error on missing directory
1421 svntest
.main
.safe_rmtree(os
.path
.join(wc_dir
, 'A', 'B', 'E'))
1422 svntest
.actions
.run_and_verify_svn(None, None, [],
1424 os
.path
.join(wc_dir
, 'A', 'B'))
1426 # Failed with "already locked" error on new dir
1427 svntest
.actions
.run_and_verify_svn(None, None, [],
1429 repo_url
+ '/A/B/E',
1430 os
.path
.join(wc_dir
, 'A', 'D', 'G'))
1433 #----------------------------------------------------------------------
1434 def basic_add_ignores(sbox
):
1435 'ignored files in added dirs should not be added'
1441 # where dir contains some items that match the ignore list and some
1442 # do not would add all items, ignored or not.
1444 sbox
.build(read_only
= True)
1445 wc_dir
= sbox
.wc_dir
1447 dir_path
= os
.path
.join(wc_dir
, 'dir')
1448 foo_c_path
= os
.path
.join(dir_path
, 'foo.c')
1449 foo_o_path
= os
.path
.join(dir_path
, 'foo.o')
1451 os
.mkdir(dir_path
, 0755)
1452 open(foo_c_path
, 'w')
1453 open(foo_o_path
, 'w')
1455 exit_code
, output
, err
= svntest
.actions
.run_and_verify_svn(
1456 "No output where some expected", svntest
.verify
.AnyOutput
, [],
1460 # If we see foo.o in the add output, fail the test.
1461 if re
.match(r
'^A\s+.*foo.o$', line
):
1462 raise svntest
.verify
.SVNUnexpectedOutput
1464 # Else never matched the unwanted output, so the test passed.
1467 #----------------------------------------------------------------------
1468 def basic_add_local_ignores(sbox
):
1469 'ignore files matching local ignores in added dirs'
1472 #svn add command not keying off svn:ignore value
1473 sbox
.build(read_only
= True)
1474 wc_dir
= sbox
.wc_dir
1476 dir_path
= os
.path
.join(wc_dir
, 'dir')
1477 file_path
= os
.path
.join(dir_path
, 'app.lock')
1479 svntest
.actions
.run_and_verify_svn(None, svntest
.verify
.AnyOutput
, [],
1481 svntest
.main
.run_svn(None, 'propset', 'svn:ignore', '*.lock', dir_path
)
1482 open(file_path
, 'w')
1483 svntest
.actions
.run_and_verify_svn(None, [], [],
1484 'add', '--force', dir_path
)
1486 #----------------------------------------------------------------------
1487 def basic_add_no_ignores(sbox
):
1488 'add ignored files in added dirs'
1490 # add ignored files using the '--no-ignore' option
1491 sbox
.build(read_only
= True)
1492 wc_dir
= sbox
.wc_dir
1494 dir_path
= os
.path
.join(wc_dir
, 'dir')
1495 foo_c_path
= os
.path
.join(dir_path
, 'foo.c')
1496 # add a few files that match the default ignore patterns
1497 foo_o_path
= os
.path
.join(dir_path
, 'foo.o')
1498 foo_lo_path
= os
.path
.join(dir_path
, 'foo.lo')
1499 foo_rej_path
= os
.path
.join(dir_path
, 'foo.rej')
1501 os
.mkdir(dir_path
, 0755)
1502 open(foo_c_path
, 'w')
1503 open(foo_o_path
, 'w')
1504 open(foo_lo_path
, 'w')
1505 open(foo_rej_path
, 'w')
1507 exit_code
, output
, err
= svntest
.actions
.run_and_verify_svn(
1508 "No output where some expected", svntest
.verify
.AnyOutput
, [],
1509 'add', '--no-ignore', dir_path
)
1512 # If we don't see ignores in the add output, fail the test.
1513 if not re
.match(r
'^A\s+.*(foo.(o|rej|lo|c)|dir)$', line
):
1514 raise svntest
.verify
.SVNUnexpectedOutput
1516 #----------------------------------------------------------------------
1517 def basic_add_parents(sbox
):
1518 'test add --parents'
1521 wc_dir
= sbox
.wc_dir
1523 X_path
= os
.path
.join(wc_dir
, 'X')
1524 Y_path
= os
.path
.join(X_path
, 'Y')
1525 Z_path
= os
.path
.join(Y_path
, 'Z')
1526 zeta_path
= os
.path
.join(Z_path
, 'zeta')
1527 omicron_path
= os
.path
.join(Y_path
, 'omicron')
1529 # Create some unversioned directories
1530 os
.mkdir(X_path
, 0755)
1531 os
.mkdir(Y_path
, 0755)
1532 os
.mkdir(Z_path
, 0755)
1535 z
= open(zeta_path
, 'w')
1536 z
.write("This is the file 'zeta'.\n")
1538 o
= open(omicron_path
, 'w')
1539 o
.write("This is the file 'omicron'.\n")
1542 # Add the file, with it's parents
1543 svntest
.actions
.run_and_verify_svn(None, None, [], 'add', '--parents',
1546 # Build expected state
1547 expected_output
= wc
.State(wc_dir
, {
1548 'X' : Item(verb
='Adding'),
1549 'X/Y' : Item(verb
='Adding'),
1550 'X/Y/Z' : Item(verb
='Adding'),
1551 'X/Y/Z/zeta' : Item(verb
='Adding'),
1554 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1555 expected_status
.add({
1556 'X' : Item(status
=' ', wc_rev
=2),
1557 'X/Y' : Item(status
=' ', wc_rev
=2),
1558 'X/Y/Z' : Item(status
=' ', wc_rev
=2),
1559 'X/Y/Z/zeta' : Item(status
=' ', wc_rev
=2),
1563 svntest
.actions
.run_and_verify_commit(wc_dir
,
1569 #----------------------------------------------------------------------
1570 def uri_syntax(sbox
):
1571 'make sure URI syntaxes are parsed correctly'
1573 sbox
.build(create_wc
= False, read_only
= True)
1574 local_dir
= sbox
.wc_dir
1576 # Revision 6638 made 'svn co http://host' seg fault, this tests the fix.
1578 scheme
= url
[:url
.find(":")]
1579 url
= scheme
+ "://some_nonexistent_host_with_no_trailing_slash"
1580 svntest
.actions
.run_and_verify_svn("No error where one expected",
1581 None, svntest
.verify
.AnyOutput
,
1582 'co', url
, local_dir
)
1584 # Different RA layers give different errors for failed checkouts;
1585 # for us, it's only important to know that it _did_ error (as
1586 # opposed to segfaulting), so we don't examine the error text.
1588 #----------------------------------------------------------------------
1589 def basic_checkout_file(sbox
):
1590 "trying to check out a file should fail"
1592 sbox
.build(read_only
= True)
1594 iota_url
= sbox
.repo_url
+ '/iota'
1596 exit_code
, output
, errput
= svntest
.main
.run_svn(1, 'co', iota_url
)
1599 if line
.find("refers to a file") != -1:
1602 raise svntest
.Failure
1604 #----------------------------------------------------------------------
1605 def basic_info(sbox
):
1606 "basic info command"
1608 def check_paths(lines
, expected_paths
):
1609 "check that paths found on input lines beginning 'Path: ' are as expected"
1612 if line
.startswith('Path: '):
1613 paths
.append(line
[6:].rstrip())
1614 if paths
!= expected_paths
:
1615 print "Reported paths:", paths
1616 print "Expected paths:", expected_paths
1617 raise svntest
.Failure
1619 sbox
.build(read_only
= True)
1621 os
.chdir(sbox
.wc_dir
)
1623 # Check that "info" works with 0, 1 and more than 1 explicit targets.
1624 exit_code
, output
, errput
= svntest
.main
.run_svn(None, 'info')
1625 check_paths(output
, ['.'])
1626 exit_code
, output
, errput
= svntest
.main
.run_svn(None, 'info', 'iota')
1627 check_paths(output
, ['iota'])
1628 exit_code
, output
, errput
= svntest
.main
.run_svn(None, 'info', 'iota', '.')
1629 check_paths(output
, ['iota', '.'])
1631 def repos_root(sbox
):
1632 "check that repos root gets set on checkout"
1634 def check_repos_root(lines
):
1636 if line
== "Repository Root: " + sbox
.repo_url
+ "\n":
1639 print "Bad or missing repository root"
1640 raise svntest
.Failure
1642 sbox
.build(read_only
= True)
1644 exit_code
, output
, errput
= svntest
.main
.run_svn(None, "info",
1646 check_repos_root(output
)
1648 exit_code
, output
, errput
= svntest
.main
.run_svn(None, "info",
1649 os
.path
.join(sbox
.wc_dir
,
1651 check_repos_root(output
)
1653 exit_code
, output
, errput
= svntest
.main
.run_svn(None, "info",
1654 os
.path
.join(sbox
.wc_dir
,
1657 check_repos_root(output
)
1659 def basic_peg_revision(sbox
):
1660 "checks peg revision on filename with @ sign"
1663 wc_dir
= sbox
.wc_dir
1664 repos_dir
= sbox
.repo_url
1665 filename
= 'abc@abc'
1667 wc_file
= wc_dir
+ '/' + filename
1668 url
= repos_dir
+ '/' + filename
1670 svntest
.main
.file_append(wc_file
, 'xyz\n')
1671 svntest
.main
.run_svn(None, 'add', wc_file
)
1672 svntest
.main
.run_svn(None,
1673 'ci', '-m', 'secret log msg', wc_file
)
1675 # Without the trailing "@", expect failure.
1676 exit_code
, output
, errlines
= svntest
.actions
.run_and_verify_svn(
1677 None, None, ".*Syntax error parsing revision 'abc'", 'cat', wc_file
)
1678 exit_code
, output
, errlines
= svntest
.actions
.run_and_verify_svn(
1679 None, None, ".*Syntax error parsing revision 'abc'", 'cat', url
)
1681 # With the trailing "@", expect success.
1682 exit_code
, output
, errlines
= svntest
.actions
.run_and_verify_svn(
1683 None, ["xyz\n"], [], 'cat', wc_file
+'@')
1684 exit_code
, output
, errlines
= svntest
.actions
.run_and_verify_svn(
1685 None, ["xyz\n"], [], 'cat', url
+'@')
1688 def info_nonhead(sbox
):
1689 "info on file not existing in HEAD"
1692 wc_dir
= sbox
.wc_dir
1693 repo_url
= sbox
.repo_url
1694 fname
= os
.path
.join(wc_dir
, 'iota')
1695 furl
= repo_url
+ "/iota"
1697 # Remove iota and commit.
1698 svntest
.actions
.run_and_verify_svn(None, None, [],
1700 expected_output
= svntest
.wc
.State(wc_dir
, {
1701 'iota' : Item(verb
='Deleting'),
1703 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1704 expected_status
.remove("iota")
1705 svntest
.actions
.run_and_verify_commit(wc_dir
,
1710 # Get info for old iota at r1.
1711 exit_code
, output
, errput
= svntest
.actions
.run_and_verify_svn(None, None,
1717 if line
.find("URL:") >= 0:
1720 print "Info didn't output an URL."
1721 raise svntest
.Failure
1725 #----------------------------------------------------------------------
1727 def ls_nonhead(sbox
):
1728 "ls a path no longer in HEAD"
1731 wc_dir
= sbox
.wc_dir
1733 # Delete A/D/rho and commit.
1734 G_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
1735 svntest
.actions
.run_and_verify_svn("error scheduling A/D/G for deletion",
1736 None, [], 'rm', G_path
)
1738 expected_output
= wc
.State(wc_dir
, {
1739 'A/D/G' : Item(verb
='Deleting'),
1742 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1743 expected_status
.remove('A/D/G', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau',)
1745 svntest
.actions
.run_and_verify_commit(wc_dir
,
1746 expected_output
, expected_status
,
1749 # Check that we can list a file in A/D/G at revision 1.
1750 rho_url
= sbox
.repo_url
+ "/A/D/G/rho"
1751 svntest
.actions
.run_and_verify_svn(None, '.* rho\n', [],
1752 'ls', '--verbose', rho_url
+ '@1')
1755 #----------------------------------------------------------------------
1757 def cat_added_PREV(sbox
):
1758 "cat added file using -rPREV"
1760 sbox
.build(read_only
= True)
1761 wc_dir
= sbox
.wc_dir
1762 f_path
= os
.path
.join(wc_dir
, 'f')
1764 # Create and add a file.
1765 svntest
.main
.file_append(f_path
, 'new text')
1766 svntest
.actions
.run_and_verify_svn("adding file",
1767 None, [], 'add', f_path
)
1769 # Cat'ing the previous version should fail.
1770 svntest
.actions
.run_and_verify_svn("cat PREV version of file",
1771 None, ".*has no committed revision.*",
1772 'cat', '-rPREV', f_path
)
1775 def ls_space_in_repo_name(sbox
):
1776 'basic ls of repos with space in name'
1778 sbox
.build(name
= "repo with spaces")
1779 wc_dir
= sbox
.wc_dir
1781 svntest
.actions
.run_and_verify_svn('ls the root of the repository',
1787 def delete_keep_local(sbox
):
1788 'delete file and directory with --keep-local'
1791 wc_dir
= sbox
.wc_dir
1792 iota_path
= os
.path
.join(wc_dir
, 'iota')
1793 C_path
= os
.path
.join(wc_dir
, 'A', 'C')
1796 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', '--keep-local',
1799 # Remove directory 'A/C'
1800 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', '--keep-local',
1804 expected_output
= wc
.State(wc_dir
, {
1805 'iota' : Item(verb
='Deleting'),
1806 'A/C' : Item(verb
='Deleting'),
1809 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1810 expected_status
.remove('iota')
1811 expected_status
.remove('A/C')
1813 svntest
.actions
.run_and_verify_commit(wc_dir
,
1819 # Update working copy to check disk state still greek tree
1820 expected_disk
= svntest
.main
.greek_state
.copy()
1821 expected_output
= svntest
.wc
.State(wc_dir
, {})
1822 expected_status
.tweak(wc_rev
= 2);
1824 svntest
.actions
.run_and_verify_update(wc_dir
,
1829 def windows_paths_in_repos(sbox
):
1830 "use folders with names like 'c:hi'"
1832 sbox
.build(create_wc
= False)
1833 repo_url
= sbox
.repo_url
1835 chi_url
= sbox
.repo_url
+ '/c:hi'
1837 # do some manipulations on a folder containing a windows drive name.
1838 svntest
.actions
.run_and_verify_svn(None, None, [],
1839 'mkdir', '-m', 'log_msg',
1842 svntest
.actions
.run_and_verify_svn(None, None, [],
1843 'rm', '-m', 'log_msg',
1846 def basic_rm_urls_one_repo(sbox
):
1847 "remotely remove directories from one repository"
1850 repo_url
= sbox
.repo_url
1851 wc_dir
= sbox
.wc_dir
1853 # Test 1: remotely delete one directory
1854 E_url
= repo_url
+ '/A/B/E'
1856 svntest
.actions
.run_and_verify_svn(None, None, [],
1857 'rm', '-m', 'log_msg',
1860 # Create expected trees and update
1861 expected_output
= svntest
.wc
.State(wc_dir
, {
1862 'A/B/E' : Item(status
='D '),
1864 expected_disk
= svntest
.main
.greek_state
.copy()
1865 expected_disk
.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
1867 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 2)
1868 expected_status
.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
1870 svntest
.actions
.run_and_verify_update(wc_dir
,
1875 # Test 2: remotely delete two directories in the same repository
1876 F_url
= repo_url
+ '/A/B/F'
1877 C_url
= repo_url
+ '/A/C'
1879 svntest
.actions
.run_and_verify_svn(None, None, [],
1880 'rm', '-m', 'log_msg',
1883 # Create expected output tree for an update of wc_backup.
1884 expected_output
= svntest
.wc
.State(wc_dir
, {
1885 'A/B/F' : Item(status
='D '),
1886 'A/C' : Item(status
='D '),
1889 # Create expected disk tree for the update
1890 expected_disk
.remove('A/B/F', 'A/C')
1892 # Create expected status tree for the update.
1893 expected_status
.tweak(wc_rev
= 3)
1894 expected_status
.remove('A/B/F', 'A/C')
1896 # Do the update and check the results in three ways.
1897 svntest
.actions
.run_and_verify_update(wc_dir
,
1902 def basic_rm_urls_multi_repos(sbox
):
1903 "remotely remove directories from two repositories"
1906 repo_url
= sbox
.repo_url
1907 repo_dir
= sbox
.repo_dir
1908 wc_dir
= sbox
.wc_dir
1910 # create a second repository and working copy
1911 other_repo_dir
, other_repo_url
= sbox
.add_repo_path("other")
1912 svntest
.main
.copy_repos(repo_dir
, other_repo_dir
, 1, 1)
1913 other_wc_dir
= sbox
.add_wc_path("other")
1914 svntest
.actions
.run_and_verify_svn("Unexpected error during co",
1915 svntest
.verify
.AnyOutput
, [], "co",
1919 # Remotely delete two x two directories in the two repositories
1920 F_url
= repo_url
+ '/A/B/F'
1921 C_url
= repo_url
+ '/A/C'
1922 F2_url
= other_repo_url
+ '/A/B/F'
1923 C2_url
= other_repo_url
+ '/A/C'
1925 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', '-m', 'log_msg',
1926 F_url
, C_url
, F2_url
, C2_url
)
1928 # Check that the two rm's to each of the repositories were handled in one
1929 # revision (per repo)
1930 expected_output
= svntest
.wc
.State(wc_dir
, {
1931 'A/B/F' : Item(status
='D '),
1932 'A/C' : Item(status
='D '),
1934 expected_disk
= svntest
.main
.greek_state
.copy()
1935 expected_disk
.remove('A/B/F', 'A/C')
1936 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 2)
1937 expected_status
.remove('A/B/F', 'A/C')
1939 svntest
.actions
.run_and_verify_update(wc_dir
,
1944 expected_status
= svntest
.actions
.get_virginal_state(other_wc_dir
, 2)
1945 expected_status
.remove('A/B/F', 'A/C')
1946 expected_output
= svntest
.wc
.State(other_wc_dir
, {
1947 'A/B/F' : Item(status
='D '),
1948 'A/C' : Item(status
='D '),
1951 svntest
.actions
.run_and_verify_update(other_wc_dir
,
1956 #-----------------------------------------------------------------------
1957 def automatic_conflict_resolution(sbox
):
1958 "automatic conflict resolution"
1961 wc_dir
= sbox
.wc_dir
1963 # Make a backup copy of the working copy
1964 wc_backup
= sbox
.add_wc_path('backup')
1965 svntest
.actions
.duplicate_dir(wc_dir
, wc_backup
)
1967 # Make a couple of local mods to files which will be committed
1968 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
1969 lambda_path
= os
.path
.join(wc_dir
, 'A', 'B', 'lambda')
1970 rho_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'rho')
1971 tau_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'tau')
1972 omega_path
= os
.path
.join(wc_dir
, 'A', 'D', 'H', 'omega')
1973 svntest
.main
.file_append(mu_path
, 'Original appended text for mu\n')
1974 svntest
.main
.file_append(lambda_path
, 'Original appended text for lambda\n')
1975 svntest
.main
.file_append(rho_path
, 'Original appended text for rho\n')
1976 svntest
.main
.file_append(tau_path
, 'Original appended text for tau\n')
1977 svntest
.main
.file_append(omega_path
, 'Original appended text for omega\n')
1979 # Make a couple of local mods to files which will be conflicted
1980 mu_path_backup
= os
.path
.join(wc_backup
, 'A', 'mu')
1981 lambda_path_backup
= os
.path
.join(wc_backup
, 'A', 'B', 'lambda')
1982 rho_path_backup
= os
.path
.join(wc_backup
, 'A', 'D', 'G', 'rho')
1983 tau_path_backup
= os
.path
.join(wc_backup
, 'A', 'D', 'G', 'tau')
1984 omega_path_backup
= os
.path
.join(wc_backup
, 'A', 'D', 'H', 'omega')
1985 svntest
.main
.file_append(mu_path_backup
,
1986 'Conflicting appended text for mu\n')
1987 svntest
.main
.file_append(lambda_path_backup
,
1988 'Conflicting appended text for lambda\n')
1989 svntest
.main
.file_append(rho_path_backup
,
1990 'Conflicting appended text for rho\n')
1991 svntest
.main
.file_append(tau_path_backup
,
1992 'Conflicting appended text for tau\n')
1993 svntest
.main
.file_append(omega_path_backup
,
1994 'Conflicting appended text for omega\n')
1996 # Created expected output tree for 'svn ci'
1997 expected_output
= wc
.State(wc_dir
, {
1998 'A/mu' : Item(verb
='Sending'),
1999 'A/B/lambda' : Item(verb
='Sending'),
2000 'A/D/G/rho' : Item(verb
='Sending'),
2001 'A/D/G/tau' : Item(verb
='Sending'),
2002 'A/D/H/omega' : Item(verb
='Sending'),
2005 # Create expected status tree; all local revisions should be at 1,
2006 # but lambda, mu and rho should be at revision 2.
2007 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
2008 expected_status
.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/G/tau',
2009 'A/D/H/omega', wc_rev
=2)
2012 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
2013 expected_status
, None, wc_dir
)
2015 # Create expected output tree for an update of the wc_backup.
2016 expected_output
= wc
.State(wc_backup
, {
2017 'A/mu' : Item(status
='C '),
2018 'A/B/lambda' : Item(status
='C '),
2019 'A/D/G/rho' : Item(status
='C '),
2020 'A/D/G/tau' : Item(status
='C '),
2021 'A/D/H/omega' : Item(status
='C '),
2024 # Create expected disk tree for the update.
2025 expected_disk
= svntest
.main
.greek_state
.copy()
2026 expected_disk
.tweak('A/B/lambda',
2027 contents
="\n".join(["This is the file 'lambda'.",
2029 "Conflicting appended text for lambda",
2031 "Original appended text for lambda",
2034 expected_disk
.tweak('A/mu',
2035 contents
="\n".join(["This is the file 'mu'.",
2037 "Conflicting appended text for mu",
2039 "Original appended text for mu",
2042 expected_disk
.tweak('A/D/G/rho',
2043 contents
="\n".join(["This is the file 'rho'.",
2045 "Conflicting appended text for rho",
2047 "Original appended text for rho",
2050 expected_disk
.tweak('A/D/G/tau',
2051 contents
="\n".join(["This is the file 'tau'.",
2053 "Conflicting appended text for tau",
2055 "Original appended text for tau",
2058 expected_disk
.tweak('A/D/H/omega',
2059 contents
="\n".join(["This is the file 'omega'.",
2061 "Conflicting appended text for omega",
2063 "Original appended text for omega",
2067 # Create expected status tree for the update.
2068 expected_status
= svntest
.actions
.get_virginal_state(wc_backup
, '2')
2069 expected_status
.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/G/tau',
2070 'A/D/H/omega', status
='C ')
2072 # "Extra" files that we expect to result from the conflicts.
2073 # These are expressed as list of regexps. What a cool system! :-)
2074 extra_files
= ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine',
2075 'lambda.*\.r1', 'lambda.*\.r2', 'lambda.*\.mine',
2076 'omega.*\.r1', 'omega.*\.r2', 'omega.*\.mine',
2077 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine',
2078 'tau.*\.r1', 'tau.*\.r2', 'tau.*\.mine',
2081 # Do the update and check the results in three ways.
2082 # All "extra" files are passed to detect_conflict_files().
2083 svntest
.actions
.run_and_verify_update(wc_backup
,
2088 svntest
.tree
.detect_conflict_files
,
2091 # verify that the extra_files list is now empty.
2092 if len(extra_files
) != 0:
2093 # Because we want to be a well-behaved test, we silently raise if
2094 # the test fails. However, these two print statements would
2095 # probably reveal the cause for the failure, if they were
2098 # print "Not all extra reject files have been accounted for:"
2100 ### we should raise a less generic error here. which?
2101 raise svntest
.Failure
2103 # So now lambda, mu and rho are all in a "conflicted" state. Run 'svn
2104 # resolve' with the respective "--accept[mine|orig|repo]" flag.
2106 # But first, check --accept actions resolved does not accept.
2107 svntest
.actions
.run_and_verify_svn(None,
2110 ".*invalid 'accept' ARG",
2111 'resolve', '--accept=postpone')
2112 svntest
.actions
.run_and_verify_svn(None,
2115 ".*invalid 'accept' ARG",
2116 'resolve', '--accept=edit')
2117 svntest
.actions
.run_and_verify_svn(None,
2120 ".*invalid 'accept' ARG",
2121 'resolve', '--accept=launch')
2122 # Run 'svn resolved --accept=NOPE. Using omega for the test.
2123 svntest
.actions
.run_and_verify_svn("Resolve command", None,
2124 ".*NOPE' is not a valid --accept value",
2129 # Resolve lambda, mu, and rho with different --accept options.
2130 svntest
.actions
.run_and_verify_svn("Resolve command", None, [],
2131 'resolve', '--accept=base',
2133 svntest
.actions
.run_and_verify_svn("Resolve command", None, [],
2135 '--accept=mine-full',
2137 svntest
.actions
.run_and_verify_svn("Resolve command", None, [],
2139 '--accept=theirs-full',
2141 fp
= open(tau_path_backup
, 'w')
2142 fp
.write("Resolution text for 'tau'.\n")
2144 svntest
.actions
.run_and_verify_svn("Resolve command", None, [],
2149 # Set the expected disk contents for the test
2150 expected_disk
= svntest
.main
.greek_state
.copy()
2152 expected_disk
.tweak('A/B/lambda', contents
="This is the file 'lambda'.\n")
2153 expected_disk
.tweak('A/mu', contents
="This is the file 'mu'.\n"
2154 "Conflicting appended text for mu\n")
2155 expected_disk
.tweak('A/D/G/rho', contents
="This is the file 'rho'.\n"
2156 "Original appended text for rho\n")
2157 expected_disk
.tweak('A/D/G/tau', contents
="Resolution text for 'tau'.\n")
2158 expected_disk
.tweak('A/D/H/omega',
2159 contents
="\n".join(["This is the file 'omega'.",
2161 "Conflicting appended text for omega",
2163 "Original appended text for omega",
2167 # Set the expected extra files for the test
2168 extra_files
= ['omega.*\.r1', 'omega.*\.r2', 'omega.*\.mine',]
2170 # Set the expected status for the test
2171 expected_status
= svntest
.actions
.get_virginal_state(wc_backup
, 2)
2172 expected_status
.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/G/tau',
2173 'A/D/H/omega', wc_rev
=2)
2175 expected_status
.tweak('A/mu', status
='M ')
2176 expected_status
.tweak('A/B/lambda', status
='M ')
2177 expected_status
.tweak('A/D/G/rho', status
=' ')
2178 expected_status
.tweak('A/D/G/tau', status
='M ')
2179 expected_status
.tweak('A/D/H/omega', status
='C ')
2181 # Set the expected output for the test
2182 expected_output
= wc
.State(wc_backup
, {})
2184 # Do the update and check the results in three ways.
2185 svntest
.actions
.run_and_verify_update(wc_backup
,
2190 svntest
.tree
.detect_conflict_files
,
2193 def info_nonexisting_file(sbox
):
2194 "get info on a file not in the repo"
2196 sbox
.build(create_wc
= False, read_only
= True)
2197 idonotexist_url
= sbox
.repo_url
+ '/IdoNotExist'
2198 exit_code
, output
, errput
= svntest
.main
.run_svn(1, 'info', idonotexist_url
)
2200 # Check for the correct error message
2202 if re
.match(".*\(Not a valid URL\).*", line
):
2205 # Else never matched the expected error output, so the test failed.
2206 raise svntest
.main
.SVNUnmatchedError
2209 #----------------------------------------------------------------------
2212 # Use blame to test three specific cases for relative url support.
2213 def basic_relative_url_using_current_dir(sbox
):
2214 "basic relative url target using current dir"
2216 # We'll use blame to test relative url parsing
2219 # First, make a new revision of iota.
2220 iota
= os
.path
.join(sbox
.wc_dir
, 'iota')
2221 svntest
.main
.file_append(iota
, "New contents for iota\n")
2222 svntest
.main
.run_svn(None, 'ci',
2226 " 1 jrandom This is the file 'iota'.\n",
2227 " 2 jrandom New contents for iota\n",
2230 orig_dir
= os
.getcwd()
2231 os
.chdir(sbox
.wc_dir
)
2233 exit_code
, output
, error
= svntest
.actions
.run_and_verify_svn(None,
2234 expected_output
, [],
2239 def basic_relative_url_using_other_targets(sbox
):
2240 "basic relative url target using other targets"
2244 # First, make a new revision of iota.
2245 iota
= os
.path
.join(sbox
.wc_dir
, 'iota')
2246 svntest
.main
.file_append(iota
, "New contents for iota\n")
2247 svntest
.main
.run_svn(None, 'ci',
2250 # Now, make a new revision of A/mu .
2251 mu
= os
.path
.join(sbox
.wc_dir
, 'A', 'mu')
2252 mu_url
= sbox
.repo_url
+ '/A/mu'
2254 svntest
.main
.file_append(mu
, "New contents for mu\n")
2255 svntest
.main
.run_svn(None, 'ci',
2260 " 1 jrandom This is the file 'iota'.\n",
2261 " 2 jrandom New contents for iota\n",
2262 " 1 jrandom This is the file 'mu'.\n",
2263 " 3 jrandom New contents for mu\n",
2266 exit_code
, output
, error
= svntest
.actions
.run_and_verify_svn(None,
2267 expected_output
, [], 'blame',
2270 def basic_relative_url_multi_repo(sbox
):
2271 "basic relative url target with multiple repos"
2274 repo_url1
= sbox
.repo_url
2275 repo_dir1
= sbox
.repo_dir
2276 wc_dir1
= sbox
.wc_dir
2278 repo_dir2
, repo_url2
= sbox
.add_repo_path("other")
2279 svntest
.main
.copy_repos(repo_dir1
, repo_dir2
, 1, 1)
2280 wc_dir2
= sbox
.add_wc_path("other")
2281 svntest
.actions
.run_and_verify_svn("Unexpected error during co",
2282 svntest
.verify
.AnyOutput
, [], "co",
2286 # Don't bother with making new revisions, the command should not work.
2287 iota_url_repo1
= repo_url1
+ '/iota'
2288 iota_url_repo2
= repo_url2
+ '/iota'
2290 exit_code
, output
, error
= svntest
.actions
.run_and_verify_svn(None, [],
2291 svntest
.verify
.AnyOutput
, 'blame',
2292 '^/A/mu', iota_url_repo1
, iota_url_repo2
)
2295 #----------------------------------------------------------------------
2297 ########################################################################
2300 # list all tests here, starting with None:
2307 basic_mkdir_url_with_parents
,
2308 basic_mkdir_wc_with_parents
,
2310 basic_merging_update
,
2316 basic_checkout_deleted
,
2317 basic_node_kind_change
,
2321 nonexistent_repository
,
2326 basic_checkout_file
,
2328 basic_add_local_ignores
,
2329 basic_add_no_ignores
,
2335 ls_space_in_repo_name
,
2337 windows_paths_in_repos
,
2338 basic_rm_urls_one_repo
,
2339 XFail(basic_rm_urls_multi_repos
),
2340 automatic_conflict_resolution
,
2341 info_nonexisting_file
,
2342 basic_relative_url_using_current_dir
,
2343 basic_relative_url_using_other_targets
,
2344 basic_relative_url_multi_repo
,
2347 if __name__
== '__main__':
2348 svntest
.main
.run_tests(test_list
)