In the command-line client, forbid
[svn.git] / subversion / tests / cmdline / basic_tests.py
blob9a3da7ba7e73b2cedd561431dee2612bba9b6b5e
1 #!/usr/bin/env python
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 ######################################################################
19 # General modules
20 import shutil, stat, re, os
22 # Our testing module
23 import svntest
24 from svntest import wc
26 # (abbreviation)
27 Skip = svntest.testcase.Skip
28 XFail = svntest.testcase.XFail
29 Item = wc.StateItem
31 ######################################################################
32 # Tests
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()
42 wc_dir = sbox.wc_dir
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",
49 'co', A_url,
50 wc_dir)
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',
65 'A/D/G/pi',
66 'A/D/G/rho',
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
72 url = sbox.repo_url
74 svntest.actions.run_and_verify_svn("Repeat checkout failed", None, [],
75 'co', url,
76 wc_dir)
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()
89 wc_dir = sbox.wc_dir
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"
105 sbox.build()
106 wc_dir = sbox.wc_dir
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,
126 expected_output,
127 expected_status,
128 None,
129 None, None,
130 None, None,
131 wc_dir)
134 #----------------------------------------------------------------------
136 def basic_update(sbox):
137 "basic update command"
139 sbox.build()
140 wc_dir = sbox.wc_dir
142 # Make a backup copy of the working copy
143 wc_backup = sbox.add_wc_path('backup')
144 svntest.actions.duplicate_dir(wc_dir, wc_backup)
146 # Make a couple of local mods to files
147 mu_path = os.path.join(wc_dir, 'A', 'mu')
148 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
149 svntest.main.file_append(mu_path, 'appended mu text')
150 svntest.main.file_append(rho_path, 'new appended text for rho')
152 # Created expected output tree for 'svn ci'
153 expected_output = wc.State(wc_dir, {
154 'A/mu' : Item(verb='Sending'),
155 'A/D/G/rho' : Item(verb='Sending'),
158 # Create expected status tree; all local revisions should be at 1,
159 # but mu and rho should be at revision 2.
160 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
161 expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2)
163 # Commit.
164 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
165 expected_status, None,
166 None, None, None, None, wc_dir)
168 # Create expected output tree for an update of the wc_backup.
169 expected_output = wc.State(wc_backup, {
170 'A/mu' : Item(status='U '),
171 'A/D/G/rho' : Item(status='U '),
174 # Create expected disk tree for the update.
175 expected_disk = svntest.main.greek_state.copy()
176 expected_disk.tweak('A/mu',
177 contents=expected_disk.desc['A/mu'].contents
178 + 'appended mu text')
179 expected_disk.tweak('A/D/G/rho',
180 contents=expected_disk.desc['A/D/G/rho'].contents
181 + 'new appended text for rho')
183 # Create expected status tree for the update.
184 expected_status = svntest.actions.get_virginal_state(wc_backup, 2)
186 # Do the update and check the results in three ways.
187 svntest.actions.run_and_verify_update(wc_backup,
188 expected_output,
189 expected_disk,
190 expected_status)
192 # Unversioned paths, those that are not immediate children of a versioned
193 # path, are skipped and do not raise an error
194 xx_path = os.path.join(wc_dir, 'xx', 'xx')
195 out, err = svntest.actions.run_and_verify_svn("update xx/xx",
196 ["Skipped '"+xx_path+"'\n"], [],
197 'update', xx_path)
198 out, err = svntest.actions.run_and_verify_svn("update xx/xx",
199 [], [],
200 'update', '--quiet', xx_path)
202 # URL's are also skipped.
203 urls = ('http://localhost/a/b/c', 'http://localhost', 'svn://localhost')
204 for url in urls:
205 out, err = svntest.actions.run_and_verify_svn("update " + url,
206 ["Skipped '"+url+"'\n"], [],
207 'update', url)
209 #----------------------------------------------------------------------
210 def basic_mkdir_url(sbox):
211 "basic mkdir URL"
213 sbox.build()
215 Y_url = sbox.repo_url + '/Y'
216 Y_Z_url = sbox.repo_url + '/Y/Z'
218 svntest.actions.run_and_verify_svn("mkdir URL URL/subdir",
219 ["\n", "Committed revision 2.\n"], [],
220 'mkdir', '-m', 'log_msg', Y_url, Y_Z_url)
222 expected_output = wc.State(sbox.wc_dir, {
223 'Y' : Item(status='A '),
224 'Y/Z' : Item(status='A '),
226 expected_disk = svntest.main.greek_state.copy()
227 expected_disk.add({
228 'Y' : Item(),
229 'Y/Z' : Item()
231 expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2)
232 expected_status.add({
233 'Y' : Item(status=' ', wc_rev=2),
234 'Y/Z' : Item(status=' ', wc_rev=2)
237 svntest.actions.run_and_verify_update(sbox.wc_dir,
238 expected_output,
239 expected_disk,
240 expected_status)
243 #----------------------------------------------------------------------
244 def basic_mkdir_url_with_parents(sbox):
245 "basic mkdir URL, including parent directories"
247 sbox.build()
249 Y_Z_url = sbox.repo_url + '/Y/Z'
250 svntest.actions.run_and_verify_svn("erroneous mkdir URL URL/subdir",
252 ".*Try 'svn mkdir --parents' instead.*",
253 'mkdir', '-m', 'log_msg',
254 Y_Z_url)
256 svntest.actions.run_and_verify_svn("mkdir URL URL/subdir",
257 ["\n", "Committed revision 2.\n"], [],
258 'mkdir', '-m', 'log_msg',
259 '--parents', Y_Z_url)
261 expected_output = wc.State(sbox.wc_dir, {
262 'Y' : Item(status='A '),
263 'Y/Z' : Item(status='A '),
265 expected_disk = svntest.main.greek_state.copy()
266 expected_disk.add({
267 'Y' : Item(),
268 'Y/Z' : Item()
270 expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2)
271 expected_status.add({
272 'Y' : Item(status=' ', wc_rev=2),
273 'Y/Z' : Item(status=' ', wc_rev=2)
276 svntest.actions.run_and_verify_update(sbox.wc_dir,
277 expected_output,
278 expected_disk,
279 expected_status)
282 #----------------------------------------------------------------------
283 def basic_mkdir_wc_with_parents(sbox):
284 "basic mkdir, including parent directories"
286 sbox.build()
287 wc_dir = sbox.wc_dir
289 Y_Z_path = os.path.join(wc_dir, 'Y', 'Z')
291 svntest.actions.run_and_verify_svn("erroneous mkdir dir/subdir", [],
292 ".*Try 'svn mkdir --parents' instead.*",
293 'mkdir', Y_Z_path)
295 svntest.actions.run_and_verify_svn("mkdir dir/subdir", None, [],
296 'mkdir', '--parents', Y_Z_path)
299 #----------------------------------------------------------------------
300 def basic_corruption(sbox):
301 "basic corruption detection"
303 ## I always wanted a test named "basic_corruption". :-)
304 ## Here's how it works:
306 ## 1. Make a working copy at rev 1, duplicate it. Now we have
307 ## two working copies at rev 1. Call them first and second.
308 ## 2. Make a local mod to `first/A/mu'.
309 ## 3. Intentionally corrupt `first/A/.svn/text-base/mu.svn-base'.
310 ## 4. Try to commit, expect a failure.
311 ## 5. Repair the text-base, commit again, expect success.
312 ## 6. Intentionally corrupt `second/A/.svn/text-base/mu.svn-base'.
313 ## 7. Try to update `second', expect failure.
314 ## 8. Repair the text-base, update again, expect success.
316 ## Here we go...
318 sbox.build()
319 wc_dir = sbox.wc_dir
321 # Make the "other" working copy
322 other_wc = sbox.add_wc_path('other')
323 svntest.actions.duplicate_dir(wc_dir, other_wc)
325 # Make a local mod to mu
326 mu_path = os.path.join(wc_dir, 'A', 'mu')
327 svntest.main.file_append(mu_path, 'appended mu text')
329 # Created expected output tree for 'svn ci'
330 expected_output = wc.State(wc_dir, {
331 'A/mu' : Item(verb='Sending'),
334 # Create expected status tree; all local revisions should be at 1,
335 # but mu should be at revision 2.
336 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
337 expected_status.tweak('A/mu', wc_rev=2)
339 # Modify mu's text-base, so we get a checksum failure the first time
340 # we try to commit.
341 tb_dir_path = os.path.join(wc_dir, 'A',
342 svntest.main.get_admin_name(), 'text-base')
343 mu_tb_path = os.path.join(tb_dir_path, 'mu.svn-base')
344 mu_saved_tb_path = mu_tb_path + "-saved"
345 tb_dir_saved_mode = os.stat(tb_dir_path)[stat.ST_MODE]
346 mu_tb_saved_mode = os.stat(mu_tb_path)[stat.ST_MODE]
347 os.chmod(tb_dir_path, 0777) # ### What's a more portable way to do this?
348 os.chmod(mu_tb_path, 0666) # ### Would rather not use hardcoded numbers.
349 shutil.copyfile(mu_tb_path, mu_saved_tb_path)
350 svntest.main.file_append(mu_tb_path, 'Aaagggkkk, corruption!')
351 os.chmod(tb_dir_path, tb_dir_saved_mode)
352 os.chmod(mu_tb_path, mu_tb_saved_mode)
354 # This commit should fail due to text base corruption.
355 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
356 expected_status, "svn: Checksum",
357 None, None, None, None, wc_dir)
359 # Restore the uncorrupted text base.
360 os.chmod(tb_dir_path, 0777)
361 os.chmod(mu_tb_path, 0666)
362 os.remove(mu_tb_path)
363 os.rename(mu_saved_tb_path, mu_tb_path)
364 os.chmod(tb_dir_path, tb_dir_saved_mode)
365 os.chmod(mu_tb_path, mu_tb_saved_mode)
367 # This commit should succeed.
368 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
369 expected_status, None,
370 None, None, None, None, wc_dir)
372 # Create expected output tree for an update of the other_wc.
373 expected_output = wc.State(other_wc, {
374 'A/mu' : Item(status='U '),
377 # Create expected disk tree for the update.
378 expected_disk = svntest.main.greek_state.copy()
379 expected_disk.tweak('A/mu',
380 contents=expected_disk.desc['A/mu'].contents
381 + 'appended mu text')
383 # Create expected status tree for the update.
384 expected_status = svntest.actions.get_virginal_state(other_wc, 2)
386 # Modify mu's text-base, so we get a checksum failure the first time
387 # we try to update.
388 tb_dir_path = os.path.join(other_wc, 'A',
389 svntest.main.get_admin_name(), 'text-base')
390 mu_tb_path = os.path.join(tb_dir_path, 'mu.svn-base')
391 mu_saved_tb_path = mu_tb_path + "-saved"
392 tb_dir_saved_mode = os.stat(tb_dir_path)[stat.ST_MODE]
393 mu_tb_saved_mode = os.stat(mu_tb_path)[stat.ST_MODE]
394 os.chmod(tb_dir_path, 0777)
395 os.chmod(mu_tb_path, 0666)
396 shutil.copyfile(mu_tb_path, mu_saved_tb_path)
397 svntest.main.file_append(mu_tb_path, 'Aiyeeeee, corruption!\nHelp!\n')
398 os.chmod(tb_dir_path, tb_dir_saved_mode)
399 os.chmod(mu_tb_path, mu_tb_saved_mode)
401 # Do the update and check the results in three ways.
402 svntest.actions.run_and_verify_update(other_wc,
403 expected_output,
404 expected_disk,
405 expected_status,
406 "svn: Checksum", other_wc)
408 # Restore the uncorrupted text base.
409 os.chmod(tb_dir_path, 0777)
410 os.chmod(mu_tb_path, 0666)
411 os.remove(mu_tb_path)
412 os.rename(mu_saved_tb_path, mu_tb_path)
413 os.chmod(tb_dir_path, tb_dir_saved_mode)
414 os.chmod(mu_tb_path, mu_tb_saved_mode)
416 # This update should succeed. (Actually, I'm kind of astonished
417 # that this works without even an intervening "svn cleanup".)
418 svntest.actions.run_and_verify_update(other_wc,
419 expected_output,
420 expected_disk,
421 expected_status)
423 #----------------------------------------------------------------------
424 def basic_merging_update(sbox):
425 "receiving text merges as part of an update"
427 sbox.build()
428 wc_dir = sbox.wc_dir
430 # First change the greek tree to make two files 10 lines long
431 mu_path = os.path.join(wc_dir, 'A', 'mu')
432 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
433 mu_text = ""
434 rho_text = ""
435 for x in range(2,11):
436 mu_text = mu_text + '\nThis is line ' + `x` + ' in mu'
437 rho_text = rho_text + '\nThis is line ' + `x` + ' in rho'
438 svntest.main.file_append(mu_path, mu_text)
439 svntest.main.file_append(rho_path, rho_text)
441 # Create expected output tree for initial commit
442 expected_output = wc.State(wc_dir, {
443 'A/mu' : Item(verb='Sending'),
444 'A/D/G/rho' : Item(verb='Sending'),
447 # Create expected status tree; all local revisions should be at 1,
448 # but mu and rho should be at revision 2.
449 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
450 expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2)
452 # Initial commit.
453 svntest.actions.run_and_verify_commit(wc_dir,
454 expected_output,
455 expected_status,
456 None,
457 None, None, None, None,
458 wc_dir)
460 # Make a backup copy of the working copy
461 wc_backup = sbox.add_wc_path('backup')
462 svntest.actions.duplicate_dir(wc_dir, wc_backup)
464 # Make a couple of local mods to files
465 svntest.main.file_append(mu_path, ' Appended to line 10 of mu')
466 svntest.main.file_append(rho_path, ' Appended to line 10 of rho')
468 # Created expected output tree for 'svn ci'
469 expected_output = wc.State(wc_dir, {
470 'A/mu' : Item(verb='Sending'),
471 'A/D/G/rho' : Item(verb='Sending'),
474 # Create expected status tree; all local revisions should be at 1,
475 # but mu and rho should be at revision 3.
476 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
477 expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=3)
479 # Commit.
480 svntest.actions.run_and_verify_commit(wc_dir,
481 expected_output,
482 expected_status,
483 None,
484 None, None, None, None,
485 wc_dir)
487 # Make local mods to wc_backup by recreating mu and rho
488 mu_path_backup = os.path.join(wc_backup, 'A', 'mu')
489 rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho')
491 # open in 'truncate to zero then write" mode
492 backup_mu_text = 'This is the new line 1 in the backup copy of mu'
493 for x in range(2,11):
494 backup_mu_text = backup_mu_text + '\nThis is line ' + `x` + ' in mu'
495 svntest.main.file_write(mu_path_backup, backup_mu_text, 'w+')
497 backup_rho_text = 'This is the new line 1 in the backup copy of rho'
498 for x in range(2,11):
499 backup_rho_text = backup_rho_text + '\nThis is line ' + `x` + ' in rho'
500 svntest.main.file_write(rho_path_backup, backup_rho_text, 'w+')
502 # Create expected output tree for an update of the wc_backup.
503 expected_output = wc.State(wc_backup, {
504 'A/mu' : Item(status='G '),
505 'A/D/G/rho' : Item(status='G '),
508 # Create expected disk tree for the update.
509 expected_disk = svntest.main.greek_state.copy()
510 expected_disk.tweak('A/mu',
511 contents=backup_mu_text + ' Appended to line 10 of mu')
512 expected_disk.tweak('A/D/G/rho',
513 contents=backup_rho_text + ' Appended to line 10 of rho')
515 # Create expected status tree for the update.
516 expected_status = svntest.actions.get_virginal_state(wc_backup, 3)
517 expected_status.tweak('A/mu', 'A/D/G/rho', status='M ')
519 # Do the update and check the results in three ways.
520 svntest.actions.run_and_verify_update(wc_backup,
521 expected_output,
522 expected_disk,
523 expected_status)
525 #----------------------------------------------------------------------
528 def basic_conflict(sbox):
529 "basic conflict creation and resolution"
531 sbox.build()
532 wc_dir = sbox.wc_dir
534 # Make a backup copy of the working copy
535 wc_backup = sbox.add_wc_path('backup')
536 svntest.actions.duplicate_dir(wc_dir, wc_backup)
538 # Make a couple of local mods to files which will be committed
539 mu_path = os.path.join(wc_dir, 'A', 'mu')
540 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
541 svntest.main.file_append(mu_path, 'Original appended text for mu\n')
542 svntest.main.file_append(rho_path, 'Original appended text for rho\n')
544 # Make a couple of local mods to files which will be conflicted
545 mu_path_backup = os.path.join(wc_backup, 'A', 'mu')
546 rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho')
547 svntest.main.file_append(mu_path_backup,
548 'Conflicting appended text for mu\n')
549 svntest.main.file_append(rho_path_backup,
550 'Conflicting appended text for rho\n')
552 # Created expected output tree for 'svn ci'
553 expected_output = wc.State(wc_dir, {
554 'A/mu' : Item(verb='Sending'),
555 'A/D/G/rho' : Item(verb='Sending'),
558 # Create expected status tree; all local revisions should be at 1,
559 # but mu and rho should be at revision 2.
560 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
561 expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2)
563 # Commit.
564 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
565 expected_status, None,
566 None, None, None, None, wc_dir)
568 # Create expected output tree for an update of the wc_backup.
569 expected_output = wc.State(wc_backup, {
570 'A/mu' : Item(status='C '),
571 'A/D/G/rho' : Item(status='C '),
574 # Create expected disk tree for the update.
575 expected_disk = svntest.main.greek_state.copy()
576 expected_disk.tweak('A/mu',
577 contents="\n".join(["This is the file 'mu'.",
578 "<<<<<<< .mine",
579 "Conflicting appended text for mu",
580 "=======",
581 "Original appended text for mu",
582 ">>>>>>> .r2",
583 ""]))
584 expected_disk.tweak('A/D/G/rho',
585 contents="\n".join(["This is the file 'rho'.",
586 "<<<<<<< .mine",
587 "Conflicting appended text for rho",
588 "=======",
589 "Original appended text for rho",
590 ">>>>>>> .r2",
591 ""]))
593 # Create expected status tree for the update.
594 expected_status = svntest.actions.get_virginal_state(wc_backup, '2')
595 expected_status.tweak('A/mu', 'A/D/G/rho', status='C ')
597 # "Extra" files that we expect to result from the conflicts.
598 # These are expressed as list of regexps. What a cool system! :-)
599 extra_files = ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine',
600 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine',]
602 # Do the update and check the results in three ways.
603 # All "extra" files are passed to detect_conflict_files().
604 svntest.actions.run_and_verify_update(wc_backup,
605 expected_output,
606 expected_disk,
607 expected_status,
608 None,
609 svntest.tree.detect_conflict_files,
610 extra_files)
612 # verify that the extra_files list is now empty.
613 if len(extra_files) != 0:
614 # Because we want to be a well-behaved test, we silently raise if
615 # the test fails. However, these two print statements would
616 # probably reveal the cause for the failure, if they were
617 # uncommented:
619 # print "Not all extra reject files have been accounted for:"
620 # print extra_files
621 ### we should raise a less generic error here. which?
622 raise svntest.Failure
624 # So now mu and rho are both in a "conflicted" state. Run 'svn
625 # resolved' on them.
627 svntest.actions.run_and_verify_svn("Resolved command", None, [],
628 'resolved',
629 mu_path_backup,
630 rho_path_backup)
632 # See if they've changed back to plain old 'M' state.
633 expected_status.tweak('A/mu', 'A/D/G/rho', status='M ')
635 # There should be *no* extra backup files lying around the working
636 # copy after resolving the conflict; thus we're not passing a custom
637 # singleton handler.
638 svntest.actions.run_and_verify_status(wc_backup, expected_status)
641 #----------------------------------------------------------------------
643 def basic_cleanup(sbox):
644 "basic cleanup command"
646 sbox.build()
647 wc_dir = sbox.wc_dir
649 # Lock some directories.
650 B_path = os.path.join(wc_dir, 'A', 'B')
651 G_path = os.path.join(wc_dir, 'A', 'D', 'G')
652 C_path = os.path.join(wc_dir, 'A', 'C')
653 svntest.actions.lock_admin_dir(B_path)
654 svntest.actions.lock_admin_dir(G_path)
655 svntest.actions.lock_admin_dir(C_path)
657 # Verify locked status.
658 expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
659 expected_output.tweak('A/B', 'A/D/G', 'A/C', locked='L')
661 svntest.actions.run_and_verify_status(wc_dir, expected_output)
663 # corrupted/non-existing temporary directory should be restored
664 svntest.actions.remove_admin_tmp_dir(B_path)
666 # Run cleanup (### todo: cleanup doesn't currently print anything)
667 svntest.actions.run_and_verify_svn("Cleanup command", None, [],
668 'cleanup', wc_dir)
670 # Verify unlocked status.
671 expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
673 svntest.actions.run_and_verify_status(wc_dir, expected_output)
676 #----------------------------------------------------------------------
678 def basic_revert(sbox):
679 "basic revert command"
681 sbox.build()
682 wc_dir = sbox.wc_dir
684 # Modify some files and props.
685 beta_path = os.path.join(wc_dir, 'A', 'B', 'E', 'beta')
686 gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
687 iota_path = os.path.join(wc_dir, 'iota')
688 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
689 zeta_path = os.path.join(wc_dir, 'A', 'D', 'H', 'zeta')
690 svntest.main.file_append(beta_path, "Added some text to 'beta'.\n")
691 svntest.main.file_append(iota_path, "Added some text to 'iota'.\n")
692 svntest.main.file_append(rho_path, "Added some text to 'rho'.\n")
693 svntest.main.file_append(zeta_path, "Added some text to 'zeta'.\n")
695 svntest.actions.run_and_verify_svn("Add command", None, [],
696 'add', zeta_path)
697 svntest.actions.run_and_verify_svn("Add prop command", None, [],
698 'ps', 'random-prop', 'propvalue',
699 gamma_path)
700 svntest.actions.run_and_verify_svn("Add prop command", None, [],
701 'ps', 'random-prop', 'propvalue',
702 iota_path)
704 # Verify modified status.
705 expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
706 expected_output.tweak('A/B/E/beta', 'A/D/G/rho', status='M ')
707 expected_output.tweak('iota', status='MM')
708 expected_output.tweak('A/D/gamma', status=' M')
709 expected_output.add({
710 'A/D/H/zeta' : Item(status='A ', wc_rev=0),
713 svntest.actions.run_and_verify_status(wc_dir, expected_output)
715 # Run revert (### todo: revert doesn't currently print anything)
716 svntest.actions.run_and_verify_svn("Revert command", None, [],
717 'revert', beta_path)
719 svntest.actions.run_and_verify_svn("Revert command", None, [],
720 'revert', gamma_path)
722 svntest.actions.run_and_verify_svn("Revert command", None, [],
723 'revert', iota_path)
725 svntest.actions.run_and_verify_svn("Revert command", None, [],
726 'revert', rho_path)
728 svntest.actions.run_and_verify_svn("Revert command", None, [],
729 'revert', zeta_path)
731 # Verify unmodified status.
732 expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
734 svntest.actions.run_and_verify_status(wc_dir, expected_output)
736 # Now, really make sure the contents are back to their original state.
737 fp = open(beta_path, 'r')
738 lines = fp.readlines()
739 if not ((len (lines) == 1) and (lines[0] == "This is the file 'beta'.\n")):
740 print "Revert failed to restore original text."
741 raise svntest.Failure
742 fp = open(iota_path, 'r')
743 lines = fp.readlines()
744 if not ((len (lines) == 1) and (lines[0] == "This is the file 'iota'.\n")):
745 print "Revert failed to restore original text."
746 raise svntest.Failure
747 fp = open(rho_path, 'r')
748 lines = fp.readlines()
749 if not ((len (lines) == 1) and (lines[0] == "This is the file 'rho'.\n")):
750 print "Revert failed to restore original text."
751 raise svntest.Failure
752 fp = open(zeta_path, 'r')
753 lines = fp.readlines()
754 if not ((len (lines) == 1) and (lines[0] == "Added some text to 'zeta'.\n")):
755 ### we should raise a less generic error here. which?
756 raise svntest.Failure
758 # Finally, check that reverted file is not readonly
759 os.remove(beta_path)
760 svntest.actions.run_and_verify_svn(None, None, [], 'revert', beta_path)
761 if not (open(beta_path, 'rw+')):
762 raise svntest.Failure
764 # Check that a directory scheduled to be added, but physically
765 # removed, can be reverted.
766 X_path = os.path.join(wc_dir, 'X')
768 svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', X_path)
770 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
771 expected_status.add({
772 'X' : Item(status='A ', wc_rev=0),
774 svntest.actions.run_and_verify_status(wc_dir, expected_status)
775 svntest.main.safe_rmtree(X_path)
777 svntest.actions.run_and_verify_svn(None, None, [], 'revert', X_path)
779 expected_status.remove('X')
780 svntest.actions.run_and_verify_status(wc_dir, expected_status)
782 # Check that a directory scheduled for deletion, but physically
783 # removed, can be reverted.
784 E_path = os.path.join(wc_dir, 'A', 'B', 'E')
785 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
787 ### Most of the rest of this test is ineffective, due to the
788 ### problems described in issue #1611.
789 svntest.actions.run_and_verify_svn(None, None, [], 'rm', E_path)
790 svntest.main.safe_rmtree(E_path)
791 expected_status.tweak('A/B/E', status='D ')
792 expected_status.tweak('A/B/E', wc_rev='?')
793 ### FIXME: A weakness in the test framework, described in detail
794 ### in issue #1611, prevents us from checking via status. Grr.
796 # svntest.actions.run_and_verify_status(wc_dir, expected_status,
797 # None, None, None, None)
800 ### If you were to uncomment the above, you'd get an error like so:
802 # =============================================================
803 # Expected E and actual E are different!
804 # =============================================================
805 # EXPECTED NODE TO BE:
806 # =============================================================
807 # * Node name: E
808 # Path: working_copies/basic_tests-10/A/B/E
809 # Contents: None
810 # Properties: {}
811 # Attributes: {'status': 'D ', 'wc_rev': '?'}
812 # Children: 2
813 # =============================================================
814 # ACTUAL NODE FOUND:
815 # =============================================================
816 # * Node name: E
817 # Path: working_copies/basic_tests-10/A/B/E
818 # Contents: None
819 # Properties: {}
820 # Attributes: {'status': 'D ', 'wc_rev': '?'}
821 # Children: is a file.
822 # Unequal Types: one Node is a file, the other is a directory
824 # This will actually print
826 # "Failed to revert 'working_copies/basic_tests-10/A/B/E' -- \
827 # try updating instead."
829 # ...but due to test suite lossage, it'll still look like success.
830 svntest.actions.run_and_verify_svn(None, None, [], 'revert', E_path)
832 ### FIXME: Again, the problem described in issue #1611 bites us here.
834 # expected_status.tweak('A/B/E', status=' ')
835 # svntest.actions.run_and_verify_status(wc_dir, expected_status,
836 # None, None, None, None)
839 #----------------------------------------------------------------------
841 def basic_switch(sbox):
842 "basic switch command"
844 sbox.build()
845 wc_dir = sbox.wc_dir
847 ### Switch the file `iota' to `A/D/gamma'.
849 # Construct some paths for convenience
850 iota_path = os.path.join(wc_dir, 'iota')
851 gamma_url = sbox.repo_url + '/A/D/gamma'
853 # Create expected output tree
854 expected_output = wc.State(wc_dir, {
855 'iota' : Item(status='U '),
858 # Create expected disk tree (iota will have gamma's contents)
859 expected_disk = svntest.main.greek_state.copy()
860 expected_disk.tweak('iota',
861 contents=expected_disk.desc['A/D/gamma'].contents)
863 # Create expected status tree
864 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
865 expected_status.tweak('iota', switched='S')
867 # Do the switch and check the results in three ways.
868 svntest.actions.run_and_verify_switch(wc_dir, iota_path, gamma_url,
869 expected_output,
870 expected_disk,
871 expected_status)
873 ### Switch the directory `A/D/H' to `A/D/G'.
875 # Construct some paths for convenience
876 ADH_path = os.path.join(wc_dir, 'A', 'D', 'H')
877 chi_path = os.path.join(ADH_path, 'chi')
878 omega_path = os.path.join(ADH_path, 'omega')
879 psi_path = os.path.join(ADH_path, 'psi')
880 pi_path = os.path.join(ADH_path, 'pi')
881 tau_path = os.path.join(ADH_path, 'tau')
882 rho_path = os.path.join(ADH_path, 'rho')
883 ADG_url = sbox.repo_url + '/A/D/G'
885 # Create expected output tree
886 expected_output = wc.State(wc_dir, {
887 'A/D/H/chi' : Item(status='D '),
888 'A/D/H/omega' : Item(status='D '),
889 'A/D/H/psi' : Item(status='D '),
890 'A/D/H/pi' : Item(status='A '),
891 'A/D/H/rho' : Item(status='A '),
892 'A/D/H/tau' : Item(status='A '),
895 # Create expected disk tree (iota will have gamma's contents,
896 # A/D/H/* will look like A/D/G/*)
897 expected_disk = svntest.main.greek_state.copy()
898 expected_disk.tweak('iota',
899 contents=expected_disk.desc['A/D/gamma'].contents)
900 expected_disk.remove('A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi')
901 expected_disk.add({
902 'A/D/H/pi' : Item("This is the file 'pi'.\n"),
903 'A/D/H/rho' : Item("This is the file 'rho'.\n"),
904 'A/D/H/tau' : Item("This is the file 'tau'.\n"),
907 # Create expected status
908 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
909 expected_status.remove('A/D/H/chi',
910 'A/D/H/omega',
911 'A/D/H/psi')
912 expected_status.add({
913 'A/D/H/pi' : Item(status=' ', wc_rev=1),
914 'A/D/H/rho' : Item(status=' ', wc_rev=1),
915 'A/D/H/tau' : Item(status=' ', wc_rev=1),
917 expected_status.tweak('iota', 'A/D/H', switched='S')
919 # Do the switch and check the results in three ways.
920 svntest.actions.run_and_verify_switch(wc_dir, ADH_path, ADG_url,
921 expected_output,
922 expected_disk,
923 expected_status)
925 #----------------------------------------------------------------------
927 def verify_file_deleted(message, path):
928 try:
929 open(path, 'r')
930 except IOError:
931 return
932 if message is not None:
933 print message
934 ###TODO We should raise a less generic error here. which?
935 raise Failure
937 def verify_dir_deleted(path):
938 if not os.path.isdir(path):
939 return 0
941 return 1
943 def basic_delete(sbox):
944 "basic delete command"
946 sbox.build()
947 wc_dir = sbox.wc_dir
949 # modify text of chi
950 chi_parent_path = os.path.join(wc_dir, 'A', 'D', 'H')
951 chi_path = os.path.join(chi_parent_path, 'chi')
952 svntest.main.file_append(chi_path, 'added to chi')
954 # modify props of rho (file)
955 rho_parent_path = os.path.join(wc_dir, 'A', 'D', 'G')
956 rho_path = os.path.join(rho_parent_path, 'rho')
957 svntest.main.run_svn(None, 'ps', 'abc', 'def', rho_path)
959 # modify props of F (dir)
960 F_parent_path = os.path.join(wc_dir, 'A', 'B')
961 F_path = os.path.join(F_parent_path, 'F')
962 svntest.main.run_svn(None, 'ps', 'abc', 'def', F_path)
964 # unversioned file
965 sigma_parent_path = os.path.join(wc_dir, 'A', 'C')
966 sigma_path = os.path.join(sigma_parent_path, 'sigma')
967 svntest.main.file_append(sigma_path, 'unversioned sigma')
969 # unversioned directory
970 Q_parent_path = sigma_parent_path
971 Q_path = os.path.join(Q_parent_path, 'Q')
972 os.mkdir(Q_path)
974 # added directory hierarchies
975 X_parent_path = os.path.join(wc_dir, 'A', 'B')
976 X_path = os.path.join(X_parent_path, 'X')
977 svntest.main.run_svn(None, 'mkdir', X_path)
978 X_child_path = os.path.join(X_path, 'xi')
979 svntest.main.file_append(X_child_path, 'added xi')
980 svntest.main.run_svn(None, 'add', X_child_path)
981 Y_parent_path = os.path.join(wc_dir, 'A', 'D')
982 Y_path = os.path.join(Y_parent_path, 'Y')
983 svntest.main.run_svn(None, 'mkdir', Y_path)
985 # check status
986 expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
987 expected_output.tweak('A/D/H/chi', status='M ')
988 expected_output.tweak('A/D/G/rho', 'A/B/F', status=' M')
989 # expected_output.tweak('A/C/sigma', status='? ')
990 expected_output.add({
991 'A/B/X' : Item(status='A ', wc_rev=0),
992 'A/B/X/xi' : Item(status='A ', wc_rev=0),
993 'A/D/Y' : Item(status='A ', wc_rev=0),
996 svntest.actions.run_and_verify_status(wc_dir, expected_output)
998 # 'svn rm' that should fail
999 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1000 'rm', chi_path)
1002 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1003 'rm', chi_parent_path)
1005 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1006 'rm', rho_path)
1008 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1009 'rm', rho_parent_path)
1011 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1012 'rm', F_path)
1014 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1015 'rm', F_parent_path)
1017 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1018 'rm', sigma_path)
1020 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1021 'rm', sigma_parent_path)
1023 svntest.actions.run_and_verify_svn(None, None, svntest.verify.AnyOutput,
1024 'rm', X_path)
1026 # check status has not changed
1027 svntest.actions.run_and_verify_status(wc_dir, expected_output)
1029 # 'svn rm' that should work
1030 E_path = os.path.join(wc_dir, 'A', 'B', 'E')
1031 svntest.actions.run_and_verify_svn(None, None, [], 'rm', E_path)
1033 # 'svn rm --force' that should work
1034 svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--force',
1035 chi_parent_path)
1037 svntest.actions.run_and_verify_svn(None, None, [],
1038 'rm', '--force', rho_parent_path)
1040 svntest.actions.run_and_verify_svn(None, None, [],
1041 'rm', '--force', F_path)
1043 svntest.actions.run_and_verify_svn(None, None, [],
1044 'rm', '--force', sigma_parent_path)
1046 svntest.actions.run_and_verify_svn(None, None, [],
1047 'rm', '--force', X_path)
1049 # Deleting already removed from wc versioned item with --force
1050 iota_path = os.path.join(wc_dir, 'iota')
1051 os.remove(iota_path)
1052 svntest.actions.run_and_verify_svn(None, None, [],
1053 'rm', '--force', iota_path)
1055 # and without --force
1056 gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
1057 os.remove(gamma_path)
1058 svntest.actions.run_and_verify_svn(None, None, [], 'rm', gamma_path)
1060 # Deleting already scheduled for deletion doesn't require --force
1061 svntest.actions.run_and_verify_svn(None, None, [], 'rm', gamma_path)
1063 svntest.actions.run_and_verify_svn(None, None, [], 'rm', E_path)
1065 # check status
1066 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1067 expected_status.tweak('A/D/H',
1068 'A/D/H/chi',
1069 'A/D/H/omega',
1070 'A/D/H/psi',
1071 'A/D/G',
1072 'A/D/G/rho',
1073 'A/D/G/pi',
1074 'A/D/G/tau',
1075 'A/B/E',
1076 'A/B/E/alpha',
1077 'A/B/E/beta',
1078 'A/B/F',
1079 'A/C',
1080 'iota',
1081 'A/D/gamma', status='D ')
1082 expected_status.add({
1083 'A/D/Y' : Item(status='A ', wc_rev=0),
1086 svntest.actions.run_and_verify_status(wc_dir, expected_status)
1088 # issue 687 delete directory with uncommitted directory child
1089 svntest.actions.run_and_verify_svn(None, None, [],
1090 'rm', '--force', Y_parent_path)
1092 expected_status.tweak('A/D', status='D ')
1093 expected_status.remove('A/D/Y')
1094 svntest.actions.run_and_verify_status(wc_dir, expected_status)
1096 # check files have been removed
1097 verify_file_deleted("Failed to remove text modified file", rho_path)
1098 verify_file_deleted("Failed to remove prop modified file", chi_path)
1099 verify_file_deleted("Failed to remove unversioned file", sigma_path)
1100 verify_file_deleted("Failed to remove unmodified file",
1101 os.path.join(E_path, 'alpha'))
1103 # check versioned dir is not removed
1104 if not verify_dir_deleted(F_path):
1105 print "Removed versioned dir"
1106 ### we should raise a less generic error here. which?
1107 raise svntest.Failure
1109 # check unversioned and added dirs has been removed
1110 if verify_dir_deleted(Q_path):
1111 print "Failed to remove unversioned dir"
1112 ### we should raise a less generic error here. which?
1113 raise svntest.Failure
1114 if verify_dir_deleted(X_path):
1115 print "Failed to remove added dir"
1116 ### we should raise a less generic error here. which?
1117 raise svntest.Failure
1119 # Deleting unversioned file explicitly
1120 foo_path = os.path.join(wc_dir, 'foo')
1121 svntest.main.file_append(foo_path, 'unversioned foo')
1122 svntest.actions.run_and_verify_svn(None, None, [],
1123 'rm', '--force', foo_path)
1124 verify_file_deleted("Failed to remove unversioned file foo", foo_path)
1126 # At one stage deleting an URL dumped core
1127 iota_URL = sbox.repo_url + '/iota'
1129 svntest.actions.run_and_verify_svn(None,
1130 ["\n", "Committed revision 2.\n"], [],
1131 'rm', '-m', 'delete iota URL',
1132 iota_URL)
1134 #----------------------------------------------------------------------
1136 def basic_checkout_deleted(sbox):
1137 "checkout a path no longer in HEAD"
1139 sbox.build()
1140 wc_dir = sbox.wc_dir
1142 # Delete A/D and commit.
1143 D_path = os.path.join(wc_dir, 'A', 'D')
1144 svntest.actions.run_and_verify_svn("error scheduling A/D for deletion",
1145 None, [], 'rm', '--force', D_path)
1147 expected_output = wc.State(wc_dir, {
1148 'A/D' : Item(verb='Deleting'),
1151 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1152 expected_status.remove('A/D', 'A/D/G', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau',
1153 'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega',
1154 'A/D/gamma')
1156 svntest.actions.run_and_verify_commit(wc_dir,
1157 expected_output, expected_status,
1158 None, None, None, None, None,
1159 wc_dir)
1161 # Now try to checkout revision 1 of A/D.
1162 url = sbox.repo_url + '/A/D'
1163 wc2 = os.path.join(sbox.wc_dir, 'new_D')
1164 svntest.actions.run_and_verify_svn("error checking out r1 of A/D",
1165 None, [], 'co', '-r', '1',
1166 url + "@1", wc2)
1168 #----------------------------------------------------------------------
1170 # Issue 846, changing a deleted file to an added directory is not
1171 # supported.
1173 def basic_node_kind_change(sbox):
1174 "attempt to change node kind"
1176 sbox.build()
1177 wc_dir = sbox.wc_dir
1179 # Schedule a file for deletion
1180 gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
1181 svntest.main.run_svn(None, 'rm', gamma_path)
1183 # Status shows deleted file
1184 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1185 expected_status.tweak('A/D/gamma', status='D ')
1186 svntest.actions.run_and_verify_status(wc_dir, expected_status)
1188 # Try and fail to create a directory (file scheduled for deletion)
1189 svntest.actions.run_and_verify_svn('Cannot change node kind',
1190 None, svntest.verify.AnyOutput,
1191 'mkdir', gamma_path)
1193 # Status is unchanged
1194 svntest.actions.run_and_verify_status(wc_dir, expected_status)
1196 # Commit file deletion
1197 expected_output = wc.State(wc_dir, {
1198 'A/D/gamma' : Item(verb='Deleting'),
1200 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1201 expected_status.remove('A/D/gamma')
1202 svntest.actions.run_and_verify_commit(wc_dir,
1203 expected_output, expected_status,
1204 None, None, None, None, None,
1205 wc_dir)
1207 # Try and fail to create a directory (file deleted)
1208 svntest.actions.run_and_verify_svn('Cannot change node kind',
1209 None, svntest.verify.AnyOutput,
1210 'mkdir', gamma_path)
1212 # Status is unchanged
1213 svntest.actions.run_and_verify_status(wc_dir, expected_status)
1215 # Update to finally get rid of file
1216 svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
1218 # mkdir should succeed
1219 svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', gamma_path)
1221 expected_status.tweak(wc_rev=2)
1222 expected_status.add({
1223 'A/D/gamma' : Item(status='A ', wc_rev=0),
1225 svntest.actions.run_and_verify_status(wc_dir, expected_status)
1227 #----------------------------------------------------------------------
1229 def basic_import(sbox):
1230 "basic import of single new file"
1232 sbox.build()
1233 wc_dir = sbox.wc_dir
1235 # create a new directory with files of various permissions
1236 new_path = os.path.join(wc_dir, 'new_file')
1238 svntest.main.file_append(new_path, "some text")
1240 # import new files into repository
1241 url = sbox.repo_url + "/dirA/dirB/new_file"
1242 output, errput = svntest.actions.run_and_verify_svn(
1243 'Cannot change node kind', None, [], 'import',
1244 '-m', 'Log message for new import', new_path, url)
1246 lastline = output.pop().strip()
1247 cm = re.compile("(Committed|Imported) revision [0-9]+.")
1248 match = cm.search(lastline)
1249 if not match:
1250 ### we should raise a less generic error here. which?
1251 raise svntest.Failure
1253 # remove (uncontrolled) local file
1254 os.remove(new_path)
1256 # Create expected disk tree for the update (disregarding props)
1257 expected_disk = svntest.main.greek_state.copy()
1258 expected_disk.add({
1259 'dirA/dirB/new_file' : Item('some text'),
1262 # Create expected status tree for the update (disregarding props).
1263 # Newly imported file should be at revision 2.
1264 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1265 expected_status.add({
1266 'dirA' : Item(status=' ', wc_rev=2),
1267 'dirA/dirB' : Item(status=' ', wc_rev=2),
1268 'dirA/dirB/new_file' : Item(status=' ', wc_rev=2),
1271 # Create expected output tree for the update.
1272 expected_output = svntest.wc.State(wc_dir, {
1273 'dirA' : Item(status='A '),
1274 'dirA/dirB' : Item(status='A '),
1275 'dirA/dirB/new_file' : Item(status='A '),
1278 # do update and check three ways
1279 svntest.actions.run_and_verify_update(wc_dir,
1280 expected_output,
1281 expected_disk,
1282 expected_status,
1283 None, None, None,
1284 None, None, 1)
1286 #----------------------------------------------------------------------
1288 def basic_cat(sbox):
1289 "basic cat of files"
1291 sbox.build()
1292 wc_dir = sbox.wc_dir
1294 mu_path = os.path.join(wc_dir, 'A', 'mu')
1296 # Get repository text even if wc is modified
1297 svntest.main.file_append(mu_path, "some text")
1298 svntest.actions.run_and_verify_svn(None, ["This is the file 'mu'.\n"],
1299 [], 'cat',
1300 ###TODO is user/pass really necessary?
1301 mu_path)
1304 #----------------------------------------------------------------------
1306 def basic_ls(sbox):
1307 'basic ls'
1309 sbox.build()
1310 wc_dir = sbox.wc_dir
1312 # Even on Windows, the output will use forward slashes, so that's
1313 # what we expect below.
1315 cwd = os.getcwd()
1316 os.chdir(wc_dir)
1317 svntest.actions.run_and_verify_svn("ls implicit current directory",
1318 ["A/\n", "iota\n"],
1319 [], 'ls')
1320 os.chdir(cwd)
1322 svntest.actions.run_and_verify_svn('ls the root of working copy',
1323 ['A/\n', 'iota\n'],
1324 [], 'ls',
1325 wc_dir)
1327 svntest.actions.run_and_verify_svn('ls a working copy directory',
1328 ['B/\n', 'C/\n', 'D/\n', 'mu\n'],
1329 [], 'ls',
1330 os.path.join(wc_dir, 'A'))
1332 svntest.actions.run_and_verify_svn('ls working copy directory with -r BASE',
1333 ['B/\n', 'C/\n', 'D/\n', 'mu\n'],
1334 [], 'ls', '-r', 'BASE',
1335 os.path.join(wc_dir, 'A'))
1337 svntest.actions.run_and_verify_svn('ls a single file',
1338 ['mu\n'],
1339 [], 'ls',
1340 os.path.join(wc_dir, 'A', 'mu'))
1342 svntest.actions.run_and_verify_svn('recursive ls',
1343 ['E/\n', 'E/alpha\n', 'E/beta\n', 'F/\n',
1344 'lambda\n' ], [], 'ls', '-R',
1345 os.path.join(wc_dir, 'A', 'B'))
1348 #----------------------------------------------------------------------
1349 def nonexistent_repository(sbox):
1350 "'svn log file:///nonexistent_path' should fail"
1352 # The bug was that
1354 # $ svn log file:///nonexistent_path
1356 # would go into an infinite loop, instead of failing immediately as
1357 # it should. The loop was because svn_ra_local__split_URL() used
1358 # svn_path_split() to lop off components and look for a repository
1359 # in each shorter path in turn, depending on svn_path_is_empty()
1360 # to test if it had reached the end. Somewhere along the line we
1361 # changed the path functions (perhaps revision 3113?), and
1362 # svn_path_split() stopped cooperating with svn_path_is_empty() in
1363 # this particular context -- svn_path_split() would reach "/",
1364 # svn_path_is_empty() would correctly claim that "/" is not empty,
1365 # the next svn_path_split() would return "/" again, and so on,
1366 # forever.
1368 # This bug was fixed in revision 3150, by checking for "/"
1369 # explicitly in svn_ra_local__split_URL(). By the time you read
1370 # this, that may or may not be the settled fix, however, so check
1371 # the logs to see if anything happened later.
1373 # Anyway: this test _always_ operates on a file:/// path. Note that
1374 # if someone runs this test on a system with "/nonexistent_path" in
1375 # the root directory, the test could fail, and that's just too bad :-).
1377 output, errput = svntest.actions.run_and_verify_svn(
1378 None, None, svntest.verify.AnyOutput,
1379 'log', 'file:///nonexistent_path')
1381 for line in errput:
1382 if re.match(".*Unable to open an ra_local session to URL.*", line):
1383 return
1385 # Else never matched the expected error output, so the test failed.
1386 raise svntest.main.SVNUnmatchedError
1389 #----------------------------------------------------------------------
1390 # Issue 1064. This test is only useful if running over a non-local RA
1391 # with authentication enabled, otherwise it will pass trivially.
1392 def basic_auth_cache(sbox):
1393 "basic auth caching"
1395 sbox.build(create_wc = False)
1396 wc_dir = sbox.wc_dir
1398 repo_dir = sbox.repo_dir
1399 repo_url = sbox.repo_url
1401 # Create a working copy without auth tokens
1402 svntest.main.safe_rmtree(wc_dir)
1405 svntest.actions.run_and_verify_svn(None, None, [],
1406 'checkout',
1407 repo_url, wc_dir)
1409 # Failed with "not locked" error on missing directory
1410 svntest.main.safe_rmtree(os.path.join(wc_dir, 'A', 'B', 'E'))
1411 svntest.actions.run_and_verify_svn(None, None, [],
1412 'status', '-u',
1413 os.path.join(wc_dir, 'A', 'B'))
1415 # Failed with "already locked" error on new dir
1416 svntest.actions.run_and_verify_svn(None, None, [],
1417 'copy',
1418 repo_url + '/A/B/E',
1419 os.path.join(wc_dir, 'A', 'D', 'G'))
1422 #----------------------------------------------------------------------
1423 def basic_add_ignores(sbox):
1424 'ignored files in added dirs should not be added'
1426 # The bug was that
1428 # $ svn add dir
1430 # where dir contains some items that match the ignore list and some
1431 # do not would add all items, ignored or not.
1433 sbox.build()
1434 wc_dir = sbox.wc_dir
1436 dir_path = os.path.join(wc_dir, 'dir')
1437 foo_c_path = os.path.join(dir_path, 'foo.c')
1438 foo_o_path = os.path.join(dir_path, 'foo.o')
1440 os.mkdir(dir_path, 0755)
1441 open(foo_c_path, 'w')
1442 open(foo_o_path, 'w')
1444 output, err = svntest.actions.run_and_verify_svn(
1445 "No output where some expected", svntest.verify.AnyOutput, [],
1446 'add', dir_path)
1448 for line in output:
1449 # If we see foo.o in the add output, fail the test.
1450 if re.match(r'^A\s+.*foo.o$', line):
1451 raise svntest.verify.SVNUnexpectedOutput
1453 # Else never matched the unwanted output, so the test passed.
1456 #----------------------------------------------------------------------
1457 def basic_add_local_ignores(sbox):
1458 'ignore files matching local ignores in added dirs'
1460 #Issue #2243
1461 #svn add command not keying off svn:ignore value
1462 sbox.build()
1463 wc_dir = sbox.wc_dir
1465 dir_path = os.path.join(wc_dir, 'dir')
1466 file_path = os.path.join(dir_path, 'app.lock')
1468 svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
1469 'mkdir', dir_path)
1470 svntest.main.run_svn(None, 'propset', 'svn:ignore', '*.lock', dir_path)
1471 open(file_path, 'w')
1472 svntest.actions.run_and_verify_svn(None, [], [],
1473 'add', '--force', dir_path)
1475 #----------------------------------------------------------------------
1476 def basic_add_no_ignores(sbox):
1477 'add ignored files in added dirs'
1479 # add ignored files using the '--no-ignore' option
1480 sbox.build()
1481 wc_dir = sbox.wc_dir
1483 dir_path = os.path.join(wc_dir, 'dir')
1484 foo_c_path = os.path.join(dir_path, 'foo.c')
1485 # add a few files that match the default ignore patterns
1486 foo_o_path = os.path.join(dir_path, 'foo.o')
1487 foo_lo_path = os.path.join(dir_path, 'foo.lo')
1488 foo_rej_path = os.path.join(dir_path, 'foo.rej')
1490 os.mkdir(dir_path, 0755)
1491 open(foo_c_path, 'w')
1492 open(foo_o_path, 'w')
1493 open(foo_lo_path, 'w')
1494 open(foo_rej_path, 'w')
1496 output, err = svntest.actions.run_and_verify_svn(
1497 "No output where some expected", svntest.verify.AnyOutput, [],
1498 'add', '--no-ignore', dir_path)
1500 for line in output:
1501 # If we don't see ignores in the add output, fail the test.
1502 if not re.match(r'^A\s+.*(foo.(o|rej|lo|c)|dir)$', line):
1503 raise svntest.verify.SVNUnexpectedOutput
1505 #----------------------------------------------------------------------
1506 def basic_add_parents(sbox):
1507 'test add --parents'
1509 sbox.build()
1510 wc_dir = sbox.wc_dir
1512 X_path = os.path.join(wc_dir, 'X')
1513 Y_path = os.path.join(X_path, 'Y')
1514 Z_path = os.path.join(Y_path, 'Z')
1515 zeta_path = os.path.join(Z_path, 'zeta')
1516 omicron_path = os.path.join(Y_path, 'omicron')
1518 # Create some unversioned directories
1519 os.mkdir(X_path, 0755)
1520 os.mkdir(Y_path, 0755)
1521 os.mkdir(Z_path, 0755)
1523 # Create new files
1524 z = open(zeta_path, 'w')
1525 z.write("This is the file 'zeta'.\n")
1526 z.close()
1527 o = open(omicron_path, 'w')
1528 o.write("This is the file 'omicron'.\n")
1529 o.close()
1531 # Add the file, with it's parents
1532 svntest.actions.run_and_verify_svn(None, None, [], 'add', '--parents',
1533 zeta_path)
1535 # Build expected state
1536 expected_output = wc.State(wc_dir, {
1537 'X' : Item(verb='Adding'),
1538 'X/Y' : Item(verb='Adding'),
1539 'X/Y/Z' : Item(verb='Adding'),
1540 'X/Y/Z/zeta' : Item(verb='Adding'),
1543 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1544 expected_status.add({
1545 'X' : Item(status=' ', wc_rev=2),
1546 'X/Y' : Item(status=' ', wc_rev=2),
1547 'X/Y/Z' : Item(status=' ', wc_rev=2),
1548 'X/Y/Z/zeta' : Item(status=' ', wc_rev=2),
1551 # Commit and verify
1552 svntest.actions.run_and_verify_commit(wc_dir,
1553 expected_output,
1554 expected_status,
1555 None,
1556 None, None,
1557 None, None,
1558 wc_dir)
1560 #----------------------------------------------------------------------
1561 def uri_syntax(sbox):
1562 'make sure URI syntaxes are parsed correctly'
1564 sbox.build(create_wc = False)
1565 local_dir = sbox.wc_dir
1567 # Revision 6638 made 'svn co http://host' seg fault, this tests the fix.
1568 url = sbox.repo_url
1569 scheme = url[:url.find(":")]
1570 url = scheme + "://some_nonexistent_host_with_no_trailing_slash"
1571 svntest.actions.run_and_verify_svn("No error where one expected",
1572 None, svntest.verify.AnyOutput,
1573 'co', url, local_dir)
1575 # Different RA layers give different errors for failed checkouts;
1576 # for us, it's only important to know that it _did_ error (as
1577 # opposed to segfaulting), so we don't examine the error text.
1579 #----------------------------------------------------------------------
1580 def basic_checkout_file(sbox):
1581 "trying to check out a file should fail"
1583 sbox.build()
1585 iota_url = sbox.repo_url + '/iota'
1587 output, errput = svntest.main.run_svn(1, 'co', iota_url)
1589 for line in errput:
1590 if line.find("refers to a file") != -1:
1591 break
1592 else:
1593 raise svntest.Failure
1595 #----------------------------------------------------------------------
1596 def basic_info(sbox):
1597 "basic info command"
1599 def check_paths(lines, expected_paths):
1600 "check that paths found on input lines beginning 'Path: ' are as expected"
1601 paths = []
1602 for line in lines:
1603 if line.startswith('Path: '):
1604 paths.append(line[6:].rstrip())
1605 if paths != expected_paths:
1606 print "Reported paths:", paths
1607 print "Expected paths:", expected_paths
1608 raise svntest.Failure
1610 sbox.build()
1612 os.chdir(sbox.wc_dir)
1614 # Check that "info" works with 0, 1 and more than 1 explicit targets.
1615 output, errput = svntest.main.run_svn(None, 'info')
1616 check_paths(output, ['.'])
1617 output, errput = svntest.main.run_svn(None, 'info', 'iota')
1618 check_paths(output, ['iota'])
1619 output, errput = svntest.main.run_svn(None, 'info', 'iota', '.')
1620 check_paths(output, ['iota', '.'])
1622 def repos_root(sbox):
1623 "check that repos root gets set on checkout"
1625 def check_repos_root(lines):
1626 for line in lines:
1627 if line == "Repository Root: " + sbox.repo_url + "\n":
1628 break
1629 else:
1630 print "Bad or missing repository root"
1631 raise svntest.Failure
1633 sbox.build()
1635 output, errput = svntest.main.run_svn(None, "info",
1636 sbox.wc_dir)
1637 check_repos_root(output)
1639 output, errput = svntest.main.run_svn(None, "info",
1640 os.path.join(sbox.wc_dir, "A"))
1641 check_repos_root(output)
1643 output, errput = svntest.main.run_svn(None, "info",
1644 os.path.join(sbox.wc_dir, "A", "B",
1645 "lambda"))
1646 check_repos_root(output)
1648 def basic_peg_revision(sbox):
1649 "checks peg revision on filename with @ sign"
1651 sbox.build()
1652 wc_dir = sbox.wc_dir
1653 repos_dir = sbox.repo_url
1654 filename = 'abc@abc'
1656 wc_file = wc_dir + '/' + filename
1657 url = repos_dir + '/' + filename
1659 svntest.main.file_append(wc_file, 'xyz\n')
1660 svntest.main.run_svn(None, 'add', wc_file)
1661 svntest.main.run_svn(None,
1662 'ci', '-m', 'secret log msg', wc_file)
1664 # Without the trailing "@", expect failure.
1665 output, errlines = svntest.actions.run_and_verify_svn(\
1666 None, None, ".*Syntax error parsing revision 'abc'", 'cat', wc_file)
1667 output, errlines = svntest.actions.run_and_verify_svn(\
1668 None, None, ".*Syntax error parsing revision 'abc'", 'cat', url)
1670 # With the trailing "@", expect success.
1671 output, errlines = svntest.actions.run_and_verify_svn(None, ["xyz\n"], [],
1672 'cat', wc_file+'@')
1673 output, errlines = svntest.actions.run_and_verify_svn(None, ["xyz\n"], [],
1674 'cat', url+'@')
1677 def info_nonhead(sbox):
1678 "info on file not existing in HEAD"
1679 sbox.build()
1681 wc_dir = sbox.wc_dir
1682 repo_url = sbox.repo_url
1683 fname = os.path.join(wc_dir, 'iota')
1684 furl = repo_url + "/iota"
1686 # Remove iota and commit.
1687 svntest.actions.run_and_verify_svn(None, None, [],
1688 "delete", fname)
1689 expected_output = svntest.wc.State(wc_dir, {
1690 'iota' : Item(verb='Deleting'),
1692 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1693 expected_status.remove("iota")
1694 svntest.actions.run_and_verify_commit(wc_dir,
1695 expected_output,
1696 expected_status,
1697 None,
1698 None, None,
1699 None, None,
1700 wc_dir)
1701 # Get info for old iota at r1.
1702 output, errput = svntest.actions.run_and_verify_svn(None, None, [],
1703 'info',
1704 furl + '@1', '-r1')
1705 got_url = 0
1706 for line in output:
1707 if line.find("URL:") >= 0:
1708 got_url = 1
1709 if not got_url:
1710 print "Info didn't output an URL."
1711 raise svntest.Failure
1715 #----------------------------------------------------------------------
1716 # Issue #2442.
1717 def ls_nonhead(sbox):
1718 "ls a path no longer in HEAD"
1720 sbox.build()
1721 wc_dir = sbox.wc_dir
1723 # Delete A/D/rho and commit.
1724 G_path = os.path.join(wc_dir, 'A', 'D', 'G')
1725 svntest.actions.run_and_verify_svn("error scheduling A/D/G for deletion",
1726 None, [], 'rm', G_path)
1728 expected_output = wc.State(wc_dir, {
1729 'A/D/G' : Item(verb='Deleting'),
1732 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1733 expected_status.remove('A/D/G', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau',)
1735 svntest.actions.run_and_verify_commit(wc_dir,
1736 expected_output, expected_status,
1737 None, None, None, None, None,
1738 wc_dir)
1740 # Check that we can list a file in A/D/G at revision 1.
1741 rho_url = sbox.repo_url + "/A/D/G/rho"
1742 svntest.actions.run_and_verify_svn(None, '.* rho\n', [],
1743 'ls', '--verbose', rho_url + '@1')
1746 #----------------------------------------------------------------------
1747 # Issue #2315.
1748 def cat_added_PREV(sbox):
1749 "cat added file using -rPREV"
1751 sbox.build()
1752 wc_dir = sbox.wc_dir
1753 f_path = os.path.join(wc_dir, 'f')
1755 # Create and add a file.
1756 svntest.main.file_append(f_path, 'new text')
1757 svntest.actions.run_and_verify_svn("adding file",
1758 None, [], 'add', f_path)
1760 # Cat'ing the previous version should fail.
1761 svntest.actions.run_and_verify_svn("cat PREV version of file",
1762 None, ".*has no committed revision.*",
1763 'cat', '-rPREV', f_path)
1765 # Issue #2612.
1766 def ls_space_in_repo_name(sbox):
1767 'basic ls of repos with space in name'
1769 sbox.build(name = "repo with spaces")
1770 wc_dir = sbox.wc_dir
1772 svntest.actions.run_and_verify_svn('ls the root of the repository',
1773 ['A/\n', 'iota\n'],
1774 [], 'ls',
1775 sbox.repo_url)
1778 def delete_keep_local(sbox):
1779 'delete file and directory with --keep-local'
1781 sbox.build()
1782 wc_dir = sbox.wc_dir
1783 iota_path = os.path.join(wc_dir, 'iota')
1784 C_path = os.path.join(wc_dir, 'A', 'C')
1786 # Remove file iota
1787 svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--keep-local',
1788 iota_path)
1790 # Remove directory 'A/C'
1791 svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--keep-local',
1792 C_path)
1794 # Commit changes
1795 expected_output = wc.State(wc_dir, {
1796 'iota' : Item(verb='Deleting'),
1797 'A/C' : Item(verb='Deleting'),
1800 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1801 expected_status.remove('iota')
1802 expected_status.remove('A/C')
1804 svntest.actions.run_and_verify_commit(wc_dir,
1805 expected_output,
1806 expected_status,
1807 None,
1808 None, None,
1809 None, None,
1810 wc_dir)
1812 # Update working copy to check disk state still greek tree
1813 expected_disk = svntest.main.greek_state.copy()
1814 expected_output = svntest.wc.State(wc_dir, {})
1815 expected_status.tweak(wc_rev = 2);
1817 svntest.actions.run_and_verify_update(wc_dir,
1818 expected_output,
1819 expected_disk,
1820 expected_status)
1822 def windows_paths_in_repos(sbox):
1823 "use folders with names like 'c:hi'"
1825 sbox.build(create_wc = False)
1826 repo_url = sbox.repo_url
1828 chi_url = sbox.repo_url + '/c:hi'
1830 # do some manipulations on a folder containing a windows drive name.
1831 svntest.actions.run_and_verify_svn(None, None, [],
1832 'mkdir', '-m', 'log_msg',
1833 chi_url)
1835 svntest.actions.run_and_verify_svn(None, None, [],
1836 'rm', '-m', 'log_msg',
1837 chi_url)
1839 def basic_rm_urls_one_repo(sbox):
1840 "remotely remove directories from one repository"
1842 sbox.build()
1843 repo_url = sbox.repo_url
1844 wc_dir = sbox.wc_dir
1846 # Test 1: remotely delete one directory
1847 E_url = repo_url + '/A/B/E'
1849 svntest.actions.run_and_verify_svn(None, None, [],
1850 'rm', '-m', 'log_msg',
1851 E_url)
1853 # Create expected trees and update
1854 expected_output = svntest.wc.State(wc_dir, {
1855 'A/B/E' : Item(status='D '),
1857 expected_disk = svntest.main.greek_state.copy()
1858 expected_disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
1860 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1861 expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
1863 svntest.actions.run_and_verify_update(wc_dir,
1864 expected_output,
1865 expected_disk,
1866 expected_status)
1868 # Test 2: remotely delete two directories in the same repository
1869 F_url = repo_url + '/A/B/F'
1870 C_url = repo_url + '/A/C'
1872 svntest.actions.run_and_verify_svn(None, None, [],
1873 'rm', '-m', 'log_msg',
1874 F_url, C_url)
1876 # Create expected output tree for an update of wc_backup.
1877 expected_output = svntest.wc.State(wc_dir, {
1878 'A/B/F' : Item(status='D '),
1879 'A/C' : Item(status='D '),
1882 # Create expected disk tree for the update
1883 expected_disk.remove('A/B/F', 'A/C')
1885 # Create expected status tree for the update.
1886 expected_status.tweak(wc_rev = 3)
1887 expected_status.remove('A/B/F', 'A/C')
1889 # Do the update and check the results in three ways.
1890 svntest.actions.run_and_verify_update(wc_dir,
1891 expected_output,
1892 expected_disk,
1893 expected_status)
1895 def basic_rm_urls_multi_repos(sbox):
1896 "remotely remove directories from two repositories"
1898 sbox.build()
1899 repo_url = sbox.repo_url
1900 repo_dir = sbox.repo_dir
1901 wc_dir = sbox.wc_dir
1903 # create a second repository and working copy
1904 other_repo_dir, other_repo_url = sbox.add_repo_path("other")
1905 svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 1)
1906 other_wc_dir = sbox.add_wc_path("other")
1907 svntest.actions.run_and_verify_svn("Unexpected error during co",
1908 svntest.verify.AnyOutput, [], "co",
1909 other_repo_url,
1910 other_wc_dir)
1912 # Remotely delete two x two directories in the two repositories
1913 F_url = repo_url + '/A/B/F'
1914 C_url = repo_url + '/A/C'
1915 F2_url = other_repo_url + '/A/B/F'
1916 C2_url = other_repo_url + '/A/C'
1918 svntest.actions.run_and_verify_svn(None, None, [], 'rm', '-m', 'log_msg',
1919 F_url, C_url, F2_url, C2_url)
1921 # Check that the two rm's to each of the repositories were handled in one
1922 # revision (per repo)
1923 expected_output = svntest.wc.State(wc_dir, {
1924 'A/B/F' : Item(status='D '),
1925 'A/C' : Item(status='D '),
1927 expected_disk = svntest.main.greek_state.copy()
1928 expected_disk.remove('A/B/F', 'A/C')
1929 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1930 expected_status.remove('A/B/F', 'A/C')
1932 svntest.actions.run_and_verify_update(wc_dir,
1933 expected_output,
1934 expected_disk,
1935 expected_status)
1937 expected_status = svntest.actions.get_virginal_state(other_wc_dir, 2)
1938 expected_status.remove('A/B/F', 'A/C')
1939 expected_output = svntest.wc.State(other_wc_dir, {
1940 'A/B/F' : Item(status='D '),
1941 'A/C' : Item(status='D '),
1944 svntest.actions.run_and_verify_update(other_wc_dir,
1945 expected_output,
1946 expected_disk,
1947 expected_status)
1949 #-----------------------------------------------------------------------
1950 def automatic_conflict_resolution(sbox):
1951 "automatic conflict resolution"
1953 sbox.build()
1954 wc_dir = sbox.wc_dir
1956 # Make a backup copy of the working copy
1957 wc_backup = sbox.add_wc_path('backup')
1958 svntest.actions.duplicate_dir(wc_dir, wc_backup)
1960 # Make a couple of local mods to files which will be committed
1961 mu_path = os.path.join(wc_dir, 'A', 'mu')
1962 lambda_path = os.path.join(wc_dir, 'A', 'B', 'lambda')
1963 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
1964 omega_path = os.path.join(wc_dir, 'A', 'D', 'H', 'omega')
1965 svntest.main.file_append(mu_path, 'Original appended text for mu\n')
1966 svntest.main.file_append(lambda_path, 'Original appended text for lambda\n')
1967 svntest.main.file_append(rho_path, 'Original appended text for rho\n')
1968 svntest.main.file_append(omega_path, 'Original appended text for omega\n')
1970 # Make a couple of local mods to files which will be conflicted
1971 mu_path_backup = os.path.join(wc_backup, 'A', 'mu')
1972 lambda_path_backup = os.path.join(wc_backup, 'A', 'B', 'lambda')
1973 rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho')
1974 omega_path_backup = os.path.join(wc_backup, 'A', 'D', 'H', 'omega')
1975 svntest.main.file_append(mu_path_backup,
1976 'Conflicting appended text for mu\n')
1977 svntest.main.file_append(lambda_path_backup,
1978 'Conflicting appended text for lambda\n')
1979 svntest.main.file_append(rho_path_backup,
1980 'Conflicting appended text for rho\n')
1981 svntest.main.file_append(omega_path_backup,
1982 'Conflicting appended text for omega\n')
1984 # Created expected output tree for 'svn ci'
1985 expected_output = wc.State(wc_dir, {
1986 'A/mu' : Item(verb='Sending'),
1987 'A/B/lambda' : Item(verb='Sending'),
1988 'A/D/G/rho' : Item(verb='Sending'),
1989 'A/D/H/omega' : Item(verb='Sending'),
1992 # Create expected status tree; all local revisions should be at 1,
1993 # but lambda, mu and rho should be at revision 2.
1994 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1995 expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/H/omega',
1996 wc_rev=2)
1998 # Commit.
1999 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2000 expected_status, None,
2001 None, None, None, None, wc_dir)
2003 # Create expected output tree for an update of the wc_backup.
2004 expected_output = wc.State(wc_backup, {
2005 'A/mu' : Item(status='C '),
2006 'A/B/lambda' : Item(status='C '),
2007 'A/D/G/rho' : Item(status='C '),
2008 'A/D/H/omega' : Item(status='C '),
2011 # Create expected disk tree for the update.
2012 expected_disk = svntest.main.greek_state.copy()
2013 expected_disk.tweak('A/B/lambda',
2014 contents="\n".join([
2015 "This is the file 'lambda'.",
2016 "<<<<<<< .mine",
2017 "Conflicting appended text for lambda",
2018 "=======",
2019 "Original appended text for lambda",
2020 ">>>>>>> .r2",
2021 ""]))
2022 expected_disk.tweak('A/mu',
2023 contents="\n".join(["This is the file 'mu'.",
2024 "<<<<<<< .mine",
2025 "Conflicting appended text for mu",
2026 "=======",
2027 "Original appended text for mu",
2028 ">>>>>>> .r2",
2029 ""]))
2030 expected_disk.tweak('A/D/G/rho',
2031 contents="\n".join(["This is the file 'rho'.",
2032 "<<<<<<< .mine",
2033 "Conflicting appended text for rho",
2034 "=======",
2035 "Original appended text for rho",
2036 ">>>>>>> .r2",
2037 ""]))
2038 expected_disk.tweak('A/D/H/omega',
2039 contents="\n".join(["This is the file 'omega'.",
2040 "<<<<<<< .mine",
2041 "Conflicting appended text for omega",
2042 "=======",
2043 "Original appended text for omega",
2044 ">>>>>>> .r2",
2045 ""]))
2047 # Create expected status tree for the update.
2048 expected_status = svntest.actions.get_virginal_state(wc_backup, '2')
2049 expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/H/omega',
2050 status='C ')
2052 # "Extra" files that we expect to result from the conflicts.
2053 # These are expressed as list of regexps. What a cool system! :-)
2054 extra_files = ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine',
2055 'lambda.*\.r1', 'lambda.*\.r2', 'lambda.*\.mine',
2056 'omega.*\.r1', 'omega.*\.r2', 'omega.*\.mine',
2057 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine',]
2059 # Do the update and check the results in three ways.
2060 # All "extra" files are passed to detect_conflict_files().
2061 svntest.actions.run_and_verify_update(wc_backup,
2062 expected_output,
2063 expected_disk,
2064 expected_status,
2065 None,
2066 svntest.tree.detect_conflict_files,
2067 extra_files)
2069 # verify that the extra_files list is now empty.
2070 if len(extra_files) != 0:
2071 # Because we want to be a well-behaved test, we silently raise if
2072 # the test fails. However, these two print statements would
2073 # probably reveal the cause for the failure, if they were
2074 # uncommented:
2076 # print "Not all extra reject files have been accounted for:"
2077 # print extra_files
2078 ### we should raise a less generic error here. which?
2079 raise svntest.Failure
2081 # So now lambda, mu and rho are all in a "conflicted" state. Run 'svn
2082 # resolved' with the respective "--accept[mine|orig|repo]" flag.
2084 # But first, check --accept actions resolved does not accept.
2085 svntest.actions.run_and_verify_svn(None,
2086 # stdout, stderr
2087 None,
2088 ".*invalid 'accept' ARG",
2089 'resolved', '--accept=postpone')
2090 svntest.actions.run_and_verify_svn(None,
2091 # stdout, stderr
2092 None,
2093 ".*invalid 'accept' ARG",
2094 'resolved', '--accept=edit')
2095 svntest.actions.run_and_verify_svn(None,
2096 # stdout, stderr
2097 None,
2098 ".*invalid 'accept' ARG",
2099 'resolved', '--accept=launch')
2100 # Run 'svn resolved --accept=NOTVALID. Using omega for the test.
2101 svntest.actions.run_and_verify_svn("Resolved command", None,
2102 ".*NOTVALID' is not a valid accept value",
2103 'resolved',
2104 '--accept=NOTVALID',
2105 omega_path_backup)
2107 # Resolve lambda, mu, and rho with different --accept options.
2108 svntest.actions.run_and_verify_svn("Resolved command", None, [],
2109 'resolved', '--accept=base',
2110 lambda_path_backup)
2111 svntest.actions.run_and_verify_svn("Resolved command", None, [],
2112 'resolved',
2113 '--accept=mine',
2114 mu_path_backup)
2115 svntest.actions.run_and_verify_svn("Resolved command", None, [],
2116 'resolved',
2117 '--accept=theirs',
2118 rho_path_backup)
2120 # Set the expected disk contents for the test
2121 expected_disk = svntest.main.greek_state.copy()
2123 expected_disk.tweak('A/B/lambda', contents="This is the file 'lambda'.\n")
2124 expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n"
2125 "Conflicting appended text for mu\n")
2126 expected_disk.tweak('A/D/G/rho', contents="This is the file 'rho'.\n"
2127 "Original appended text for rho\n")
2128 expected_disk.tweak('A/D/H/omega',
2129 contents="\n".join(["This is the file 'omega'.",
2130 "<<<<<<< .mine",
2131 "Conflicting appended text for omega",
2132 "=======",
2133 "Original appended text for omega",
2134 ">>>>>>> .r2",
2135 ""]))
2137 # Set the expected extra files for the test
2138 extra_files = ['omega.*\.r1', 'omega.*\.r2', 'omega.*\.mine',]
2140 # Set the expected status for the test
2141 expected_status = svntest.actions.get_virginal_state(wc_backup, 2)
2142 expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/H/omega',
2143 wc_rev=2)
2145 expected_status.tweak('A/mu', status='M ')
2146 expected_status.tweak('A/B/lambda', status='M ')
2147 expected_status.tweak('A/D/G/rho', status=' ')
2148 expected_status.tweak('A/D/H/omega', status='C ')
2150 # Set the expected output for the test
2151 expected_output = wc.State(wc_backup, {})
2153 # Do the update and check the results in three ways.
2154 svntest.actions.run_and_verify_update(wc_backup,
2155 expected_output,
2156 expected_disk,
2157 expected_status,
2158 None,
2159 svntest.tree.detect_conflict_files,
2160 extra_files)
2162 def info_nonexisting_file(sbox):
2163 "get info on a file not in the repo"
2165 sbox.build(create_wc = False)
2166 idonotexist_url = sbox.repo_url + '/IdoNotExist'
2167 output, errput = svntest.main.run_svn(1, 'info', idonotexist_url)
2169 # Check for the correct error message
2170 for line in errput:
2171 if re.match(".*\(Not a valid URL\).*", line):
2172 return
2174 # Else never matched the expected error output, so the test failed.
2175 raise svntest.main.SVNUnmatchedError
2178 #----------------------------------------------------------------------
2180 ########################################################################
2181 # Run the tests
2183 # list all tests here, starting with None:
2184 test_list = [ None,
2185 basic_checkout,
2186 basic_status,
2187 basic_commit,
2188 basic_update,
2189 basic_mkdir_url,
2190 basic_mkdir_url_with_parents,
2191 basic_mkdir_wc_with_parents,
2192 basic_corruption,
2193 basic_merging_update,
2194 basic_conflict,
2195 basic_cleanup,
2196 basic_revert,
2197 basic_switch,
2198 basic_delete,
2199 basic_checkout_deleted,
2200 basic_node_kind_change,
2201 basic_import,
2202 basic_cat,
2203 basic_ls,
2204 nonexistent_repository,
2205 basic_auth_cache,
2206 basic_add_ignores,
2207 basic_add_parents,
2208 uri_syntax,
2209 basic_checkout_file,
2210 basic_info,
2211 basic_add_local_ignores,
2212 basic_add_no_ignores,
2213 repos_root,
2214 basic_peg_revision,
2215 info_nonhead,
2216 ls_nonhead,
2217 cat_added_PREV,
2218 ls_space_in_repo_name,
2219 delete_keep_local,
2220 windows_paths_in_repos,
2221 basic_rm_urls_one_repo,
2222 XFail(basic_rm_urls_multi_repos),
2223 automatic_conflict_resolution,
2224 info_nonexisting_file,
2227 if __name__ == '__main__':
2228 svntest.main.run_tests(test_list)
2229 # NOTREACHED
2232 ### End of file.