Fix compiler warning due to missing function prototype.
[svn.git] / subversion / tests / cmdline / basic_tests.py
blob4986a75a4ae271a14c12bc8559659a39f39e8582
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(read_only = True)
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(read_only = True)
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 wc_dir)
132 #----------------------------------------------------------------------
134 def basic_update(sbox):
135 "basic update command"
137 sbox.build()
138 wc_dir = sbox.wc_dir
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)
161 # Commit.
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,
185 expected_output,
186 expected_disk,
187 expected_status)
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"], [],
194 'update', xx_path)
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')
201 for url in urls:
202 exit_code, out, err = svntest.actions.run_and_verify_svn(
203 "update " + url, ["Skipped '"+url+"'\n"], [],
204 'update', url)
206 #----------------------------------------------------------------------
207 def basic_mkdir_url(sbox):
208 "basic mkdir URL"
210 sbox.build()
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()
224 expected_disk.add({
225 'Y' : Item(),
226 'Y/Z' : Item()
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,
235 expected_output,
236 expected_disk,
237 expected_status)
240 #----------------------------------------------------------------------
241 def basic_mkdir_url_with_parents(sbox):
242 "basic mkdir URL, including parent directories"
244 sbox.build()
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()
272 expected_disk.add({
273 'X' : Item(),
274 'X/Y' : Item(),
275 'X/Y/Z' : Item(),
276 'X/Y/Z2' : Item(),
277 'X/T' : Item(),
278 'X/T/C' : Item(),
279 'U' : Item(),
280 'U/V' : Item(),
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,
294 expected_output,
295 expected_disk,
296 expected_status)
299 #----------------------------------------------------------------------
300 def basic_mkdir_wc_with_parents(sbox):
301 "basic mkdir, including parent directories"
303 sbox.build()
304 wc_dir = sbox.wc_dir
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.*",
310 'mkdir', Y_Z_path)
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.
333 ## Here we go...
335 sbox.build()
336 wc_dir = sbox.wc_dir
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
357 # we try to commit.
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",
374 wc_dir)
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
403 # we try to update.
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,
419 expected_output,
420 expected_disk,
421 expected_status,
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,
435 expected_output,
436 expected_disk,
437 expected_status)
439 #----------------------------------------------------------------------
440 def basic_merging_update(sbox):
441 "receiving text merges as part of an update"
443 sbox.build()
444 wc_dir = sbox.wc_dir
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')
449 mu_text = ""
450 rho_text = ""
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)
468 # Initial commit.
469 svntest.actions.run_and_verify_commit(wc_dir,
470 expected_output,
471 expected_status,
472 None,
473 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)
494 # Commit.
495 svntest.actions.run_and_verify_commit(wc_dir,
496 expected_output,
497 expected_status,
498 None,
499 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,
535 expected_output,
536 expected_disk,
537 expected_status)
539 #----------------------------------------------------------------------
542 def basic_conflict(sbox):
543 "basic conflict creation and resolution"
545 sbox.build()
546 wc_dir = sbox.wc_dir
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)
577 # Commit.
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'.",
591 "<<<<<<< .mine",
592 "Conflicting appended text for mu",
593 "=======",
594 "Original appended text for mu",
595 ">>>>>>> .r2",
596 ""]))
597 expected_disk.tweak('A/D/G/rho',
598 contents="\n".join(["This is the file 'rho'.",
599 "<<<<<<< .mine",
600 "Conflicting appended text for rho",
601 "=======",
602 "Original appended text for rho",
603 ">>>>>>> .r2",
604 ""]))
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,
618 expected_output,
619 expected_disk,
620 expected_status,
621 None,
622 svntest.tree.detect_conflict_files,
623 extra_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
630 # uncommented:
632 # print "Not all extra reject files have been accounted for:"
633 # print extra_files
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
638 # resolved' on them.
640 svntest.actions.run_and_verify_svn("Resolved command", None, [],
641 'resolved',
642 mu_path_backup,
643 rho_path_backup)
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
650 # singleton handler.
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)
660 wc_dir = sbox.wc_dir
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, [],
681 'cleanup', wc_dir)
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"
694 sbox.build()
695 wc_dir = sbox.wc_dir
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, [],
709 'add', zeta_path)
710 svntest.actions.run_and_verify_svn("Add prop command", None, [],
711 'ps', 'random-prop', 'propvalue',
712 gamma_path)
713 svntest.actions.run_and_verify_svn("Add prop command", None, [],
714 'ps', 'random-prop', 'propvalue',
715 iota_path)
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, [],
730 'revert', beta_path)
732 svntest.actions.run_and_verify_svn("Revert command", None, [],
733 'revert', gamma_path)
735 svntest.actions.run_and_verify_svn("Revert command", None, [],
736 'revert', iota_path)
738 svntest.actions.run_and_verify_svn("Revert command", None, [],
739 'revert', rho_path)
741 svntest.actions.run_and_verify_svn("Revert command", None, [],
742 'revert', zeta_path)
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
772 os.remove(beta_path)
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 # =============================================================
820 # * Node name: E
821 # Path: working_copies/basic_tests-10/A/B/E
822 # Contents: None
823 # Properties: {}
824 # Attributes: {'status': 'D ', 'wc_rev': '?'}
825 # Children: 2
826 # =============================================================
827 # ACTUAL NODE FOUND:
828 # =============================================================
829 # * Node name: E
830 # Path: working_copies/basic_tests-10/A/B/E
831 # Contents: None
832 # Properties: {}
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)
858 wc_dir = sbox.wc_dir
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,
882 expected_output,
883 expected_disk,
884 expected_status)
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')
914 expected_disk.add({
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',
923 'A/D/H/omega',
924 'A/D/H/psi')
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,
934 expected_output,
935 expected_disk,
936 expected_status)
938 #----------------------------------------------------------------------
940 def verify_file_deleted(message, path):
941 try:
942 open(path, 'r')
943 except IOError:
944 return
945 if message is not None:
946 print message
947 ###TODO We should raise a less generic error here. which?
948 raise Failure
950 def verify_dir_deleted(path):
951 if not os.path.isdir(path):
952 return 0
954 return 1
956 def basic_delete(sbox):
957 "basic delete command"
959 sbox.build()
960 wc_dir = sbox.wc_dir
962 # modify text of chi
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)
977 # unversioned file
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')
985 os.mkdir(Q_path)
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)
998 # check status
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,
1013 'rm', chi_path)
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,
1019 'rm', rho_path)
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,
1025 'rm', F_path)
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,
1031 'rm', sigma_path)
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,
1037 'rm', X_path)
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',
1048 chi_parent_path)
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)
1078 # check status
1079 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1080 expected_status.tweak('A/D/H',
1081 'A/D/H/chi',
1082 'A/D/H/omega',
1083 'A/D/H/psi',
1084 'A/D/G',
1085 'A/D/G/rho',
1086 'A/D/G/pi',
1087 'A/D/G/tau',
1088 'A/B/E',
1089 'A/B/E/alpha',
1090 'A/B/E/beta',
1091 'A/B/F',
1092 'A/C',
1093 'iota',
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',
1145 iota_URL)
1147 #----------------------------------------------------------------------
1149 def basic_checkout_deleted(sbox):
1150 "checkout a path no longer in HEAD"
1152 sbox.build()
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',
1167 'A/D/gamma')
1169 svntest.actions.run_and_verify_commit(wc_dir,
1170 expected_output, expected_status,
1171 None, wc_dir)
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',
1178 url + "@1", wc2)
1180 #----------------------------------------------------------------------
1182 # Issue 846, changing a deleted file to an added directory is not
1183 # supported.
1185 def basic_node_kind_change(sbox):
1186 "attempt to change node kind"
1188 sbox.build()
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,
1216 None, wc_dir)
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"
1243 sbox.build()
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)
1260 if not match:
1261 ### we should raise a less generic error here. which?
1262 raise svntest.Failure
1264 # remove (uncontrolled) local file
1265 os.remove(new_path)
1267 # Create expected disk tree for the update (disregarding props)
1268 expected_disk = svntest.main.greek_state.copy()
1269 expected_disk.add({
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,
1291 expected_output,
1292 expected_disk,
1293 expected_status,
1294 None, None, None,
1295 None, None, 1)
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"],
1310 [], 'cat',
1311 ###TODO is user/pass really necessary?
1312 mu_path)
1315 #----------------------------------------------------------------------
1317 def basic_ls(sbox):
1318 'basic ls'
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.
1326 cwd = os.getcwd()
1327 os.chdir(wc_dir)
1328 svntest.actions.run_and_verify_svn("ls implicit current directory",
1329 ["A/\n", "iota\n"],
1330 [], 'ls')
1331 os.chdir(cwd)
1333 svntest.actions.run_and_verify_svn('ls the root of working copy',
1334 ['A/\n', 'iota\n'],
1335 [], 'ls',
1336 wc_dir)
1338 svntest.actions.run_and_verify_svn('ls a working copy directory',
1339 ['B/\n', 'C/\n', 'D/\n', 'mu\n'],
1340 [], 'ls',
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',
1349 ['mu\n'],
1350 [], 'ls',
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"
1363 # The bug was that
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,
1377 # forever.
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')
1392 for line in errput:
1393 if re.match(".*Unable to open an ra_local session to URL.*", line):
1394 return
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, [],
1417 'checkout',
1418 repo_url, wc_dir)
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, [],
1423 'status', '-u',
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, [],
1428 'copy',
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'
1437 # The bug was that
1439 # $ svn add dir
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, [],
1457 'add', dir_path)
1459 for line in output:
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'
1471 #Issue #2243
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, [],
1480 'mkdir', dir_path)
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)
1511 for line in output:
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'
1520 sbox.build()
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)
1534 # Create new files
1535 z = open(zeta_path, 'w')
1536 z.write("This is the file 'zeta'.\n")
1537 z.close()
1538 o = open(omicron_path, 'w')
1539 o.write("This is the file 'omicron'.\n")
1540 o.close()
1542 # Add the file, with it's parents
1543 svntest.actions.run_and_verify_svn(None, None, [], 'add', '--parents',
1544 zeta_path)
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),
1562 # Commit and verify
1563 svntest.actions.run_and_verify_commit(wc_dir,
1564 expected_output,
1565 expected_status,
1566 None,
1567 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.
1577 url = sbox.repo_url
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)
1598 for line in errput:
1599 if line.find("refers to a file") != -1:
1600 break
1601 else:
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"
1610 paths = []
1611 for line in lines:
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):
1635 for line in lines:
1636 if line == "Repository Root: " + sbox.repo_url + "\n":
1637 break
1638 else:
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",
1645 sbox.wc_dir)
1646 check_repos_root(output)
1648 exit_code, output, errput = svntest.main.run_svn(None, "info",
1649 os.path.join(sbox.wc_dir,
1650 "A"))
1651 check_repos_root(output)
1653 exit_code, output, errput = svntest.main.run_svn(None, "info",
1654 os.path.join(sbox.wc_dir,
1655 "A", "B",
1656 "lambda"))
1657 check_repos_root(output)
1659 def basic_peg_revision(sbox):
1660 "checks peg revision on filename with @ sign"
1662 sbox.build()
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"
1690 sbox.build()
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, [],
1699 "delete", fname)
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,
1706 expected_output,
1707 expected_status,
1708 None,
1709 wc_dir)
1710 # Get info for old iota at r1.
1711 exit_code, output, errput = svntest.actions.run_and_verify_svn(None, None,
1712 [], 'info',
1713 furl + '@1',
1714 '-r1')
1715 got_url = 0
1716 for line in output:
1717 if line.find("URL:") >= 0:
1718 got_url = 1
1719 if not got_url:
1720 print "Info didn't output an URL."
1721 raise svntest.Failure
1725 #----------------------------------------------------------------------
1726 # Issue #2442.
1727 def ls_nonhead(sbox):
1728 "ls a path no longer in HEAD"
1730 sbox.build()
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,
1747 None, wc_dir)
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 #----------------------------------------------------------------------
1756 # Issue #2315.
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)
1774 # Issue #2612.
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',
1782 ['A/\n', 'iota\n'],
1783 [], 'ls',
1784 sbox.repo_url)
1787 def delete_keep_local(sbox):
1788 'delete file and directory with --keep-local'
1790 sbox.build()
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')
1795 # Remove file iota
1796 svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--keep-local',
1797 iota_path)
1799 # Remove directory 'A/C'
1800 svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--keep-local',
1801 C_path)
1803 # Commit changes
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,
1814 expected_output,
1815 expected_status,
1816 None,
1817 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,
1825 expected_output,
1826 expected_disk,
1827 expected_status)
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',
1840 chi_url)
1842 svntest.actions.run_and_verify_svn(None, None, [],
1843 'rm', '-m', 'log_msg',
1844 chi_url)
1846 def basic_rm_urls_one_repo(sbox):
1847 "remotely remove directories from one repository"
1849 sbox.build()
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',
1858 E_url)
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,
1871 expected_output,
1872 expected_disk,
1873 expected_status)
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',
1881 F_url, C_url)
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,
1898 expected_output,
1899 expected_disk,
1900 expected_status)
1902 def basic_rm_urls_multi_repos(sbox):
1903 "remotely remove directories from two repositories"
1905 sbox.build()
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",
1916 other_repo_url,
1917 other_wc_dir)
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,
1940 expected_output,
1941 expected_disk,
1942 expected_status)
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,
1952 expected_output,
1953 expected_disk,
1954 expected_status)
1956 #-----------------------------------------------------------------------
1957 def automatic_conflict_resolution(sbox):
1958 "automatic conflict resolution"
1960 sbox.build()
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)
2011 # Commit.
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'.",
2028 "<<<<<<< .mine",
2029 "Conflicting appended text for lambda",
2030 "=======",
2031 "Original appended text for lambda",
2032 ">>>>>>> .r2",
2033 ""]))
2034 expected_disk.tweak('A/mu',
2035 contents="\n".join(["This is the file 'mu'.",
2036 "<<<<<<< .mine",
2037 "Conflicting appended text for mu",
2038 "=======",
2039 "Original appended text for mu",
2040 ">>>>>>> .r2",
2041 ""]))
2042 expected_disk.tweak('A/D/G/rho',
2043 contents="\n".join(["This is the file 'rho'.",
2044 "<<<<<<< .mine",
2045 "Conflicting appended text for rho",
2046 "=======",
2047 "Original appended text for rho",
2048 ">>>>>>> .r2",
2049 ""]))
2050 expected_disk.tweak('A/D/G/tau',
2051 contents="\n".join(["This is the file 'tau'.",
2052 "<<<<<<< .mine",
2053 "Conflicting appended text for tau",
2054 "=======",
2055 "Original appended text for tau",
2056 ">>>>>>> .r2",
2057 ""]))
2058 expected_disk.tweak('A/D/H/omega',
2059 contents="\n".join(["This is the file 'omega'.",
2060 "<<<<<<< .mine",
2061 "Conflicting appended text for omega",
2062 "=======",
2063 "Original appended text for omega",
2064 ">>>>>>> .r2",
2065 ""]))
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,
2084 expected_output,
2085 expected_disk,
2086 expected_status,
2087 None,
2088 svntest.tree.detect_conflict_files,
2089 extra_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
2096 # uncommented:
2098 # print "Not all extra reject files have been accounted for:"
2099 # print extra_files
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,
2108 # stdout, stderr
2109 None,
2110 ".*invalid 'accept' ARG",
2111 'resolve', '--accept=postpone')
2112 svntest.actions.run_and_verify_svn(None,
2113 # stdout, stderr
2114 None,
2115 ".*invalid 'accept' ARG",
2116 'resolve', '--accept=edit')
2117 svntest.actions.run_and_verify_svn(None,
2118 # stdout, stderr
2119 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",
2125 'resolve',
2126 '--accept=NOPE',
2127 omega_path_backup)
2129 # Resolve lambda, mu, and rho with different --accept options.
2130 svntest.actions.run_and_verify_svn("Resolve command", None, [],
2131 'resolve', '--accept=base',
2132 lambda_path_backup)
2133 svntest.actions.run_and_verify_svn("Resolve command", None, [],
2134 'resolve',
2135 '--accept=mine-full',
2136 mu_path_backup)
2137 svntest.actions.run_and_verify_svn("Resolve command", None, [],
2138 'resolve',
2139 '--accept=theirs-full',
2140 rho_path_backup)
2141 fp = open(tau_path_backup, 'w')
2142 fp.write("Resolution text for 'tau'.\n")
2143 fp.close()
2144 svntest.actions.run_and_verify_svn("Resolve command", None, [],
2145 'resolve',
2146 '--accept=working',
2147 tau_path_backup)
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'.",
2160 "<<<<<<< .mine",
2161 "Conflicting appended text for omega",
2162 "=======",
2163 "Original appended text for omega",
2164 ">>>>>>> .r2",
2165 ""]))
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,
2186 expected_output,
2187 expected_disk,
2188 expected_status,
2189 None,
2190 svntest.tree.detect_conflict_files,
2191 extra_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
2201 for line in errput:
2202 if re.match(".*\(Not a valid URL\).*", line):
2203 return
2205 # Else never matched the expected error output, so the test failed.
2206 raise svntest.main.SVNUnmatchedError
2209 #----------------------------------------------------------------------
2210 # Relative urls
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
2217 sbox.build()
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',
2223 '-m', '', iota)
2225 expected_output = [
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, [],
2235 'blame', '^/iota')
2237 os.chdir(orig_dir)
2239 def basic_relative_url_using_other_targets(sbox):
2240 "basic relative url target using other targets"
2242 sbox.build()
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',
2248 '-m', '', iota)
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',
2256 '-m', '', mu)
2259 expected_output = [
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',
2268 '^/iota', mu_url)
2270 def basic_relative_url_multi_repo(sbox):
2271 "basic relative url target with multiple repos"
2273 sbox.build()
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",
2283 repo_url2,
2284 wc_dir2)
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 ########################################################################
2298 # Run the tests
2300 # list all tests here, starting with None:
2301 test_list = [ None,
2302 basic_checkout,
2303 basic_status,
2304 basic_commit,
2305 basic_update,
2306 basic_mkdir_url,
2307 basic_mkdir_url_with_parents,
2308 basic_mkdir_wc_with_parents,
2309 basic_corruption,
2310 basic_merging_update,
2311 basic_conflict,
2312 basic_cleanup,
2313 basic_revert,
2314 basic_switch,
2315 basic_delete,
2316 basic_checkout_deleted,
2317 basic_node_kind_change,
2318 basic_import,
2319 basic_cat,
2320 basic_ls,
2321 nonexistent_repository,
2322 basic_auth_cache,
2323 basic_add_ignores,
2324 basic_add_parents,
2325 uri_syntax,
2326 basic_checkout_file,
2327 basic_info,
2328 basic_add_local_ignores,
2329 basic_add_no_ignores,
2330 repos_root,
2331 basic_peg_revision,
2332 info_nonhead,
2333 ls_nonhead,
2334 cat_added_PREV,
2335 ls_space_in_repo_name,
2336 delete_keep_local,
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)
2349 # NOTREACHED
2352 ### End of file.