Add a little more to the svn_rangelist_intersect test to test the
[svn.git] / subversion / tests / cmdline / switch_tests.py
blob9c3f45ec64c70a06863e2c73cb5e830cb8bfb86d
1 #!/usr/bin/env python
3 # switch_tests.py: testing `svn switch'.
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-2004 CollabNet. All rights reserved.
11 # This software is licensed as described in the file COPYING, which
12 # you should have received as part of this distribution. The terms
13 # are also available at http://subversion.tigris.org/license-1.html.
14 # If newer versions of this license are posted there, you may use a
15 # newer version instead, at your option.
17 ######################################################################
19 # General modules
20 import shutil, re, os
22 # Our testing module
23 import svntest
25 # (abbreviation)
26 Skip = svntest.testcase.Skip
27 XFail = svntest.testcase.XFail
28 Item = svntest.wc.StateItem
30 from svntest.main import SVN_PROP_MERGEINFO
32 ### Bummer. It would be really nice to have easy access to the URL
33 ### member of our entries files so that switches could be testing by
34 ### examining the modified ancestry. But status doesn't show this
35 ### information. Hopefully in the future the cmdline binary will have
36 ### a subcommand for dumping multi-line detailed information about
37 ### versioned things. Until then, we'll stick with the traditional
38 ### verification methods.
39 ###
40 ### gjs says: we have 'svn info' now
42 def get_routine_status_state(wc_dir):
43 """get the routine status list for WC_DIR at the completion of an
44 initial call to do_routine_switching()"""
46 # Construct some paths for convenience
47 ADH_path = os.path.join(wc_dir, 'A', 'D', 'H')
48 chi_path = os.path.join(ADH_path, 'chi')
49 omega_path = os.path.join(ADH_path, 'omega')
50 psi_path = os.path.join(ADH_path, 'psi')
51 pi_path = os.path.join(ADH_path, 'pi')
52 tau_path = os.path.join(ADH_path, 'tau')
53 rho_path = os.path.join(ADH_path, 'rho')
55 # Now generate a state
56 state = svntest.actions.get_virginal_state(wc_dir, 1)
57 state.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda')
58 state.add({
59 'A/B/pi' : Item(status=' ', wc_rev=1),
60 'A/B/tau' : Item(status=' ', wc_rev=1),
61 'A/B/rho' : Item(status=' ', wc_rev=1),
64 return state
66 #----------------------------------------------------------------------
68 def get_routine_disk_state(wc_dir):
69 """get the routine disk list for WC_DIR at the completion of an
70 initial call to do_routine_switching()"""
72 disk = svntest.main.greek_state.copy()
74 # iota has the same contents as gamma
75 disk.tweak('iota', contents=disk.desc['A/D/gamma'].contents)
77 # A/B/* no longer exist, but have been replaced by copies of A/D/G/*
78 disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda')
79 disk.add({
80 'A/B/pi' : Item("This is the file 'pi'.\n"),
81 'A/B/rho' : Item("This is the file 'rho'.\n"),
82 'A/B/tau' : Item("This is the file 'tau'.\n"),
85 return disk
87 #----------------------------------------------------------------------
89 def do_routine_switching(wc_dir, repo_url, verify):
90 """perform some routine switching of the working copy WC_DIR for
91 other tests to use. If VERIFY, then do a full verification of the
92 switching, else don't bother."""
94 ### Switch the file `iota' to `A/D/gamma'.
96 # Construct some paths for convenience
97 iota_path = os.path.join(wc_dir, 'iota')
98 gamma_url = repo_url + '/A/D/gamma'
100 if verify:
101 # Create expected output tree
102 expected_output = svntest.wc.State(wc_dir, {
103 'iota' : Item(status='U '),
106 # Create expected disk tree (iota will have gamma's contents)
107 expected_disk = svntest.main.greek_state.copy()
108 expected_disk.tweak('iota',
109 contents=expected_disk.desc['A/D/gamma'].contents)
111 # Create expected status tree
112 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
113 expected_status.tweak('iota', switched='S')
115 # Do the switch and check the results in three ways.
116 svntest.actions.run_and_verify_switch(wc_dir, iota_path, gamma_url,
117 expected_output,
118 expected_disk,
119 expected_status)
120 else:
121 svntest.main.run_svn(None, 'switch',
122 gamma_url, iota_path)
124 ### Switch the directory `A/B' to `A/D/G'.
126 # Construct some paths for convenience
127 AB_path = os.path.join(wc_dir, 'A', 'B')
128 ADG_url = repo_url + '/A/D/G'
130 if verify:
131 # Create expected output tree
132 expected_output = svntest.wc.State(wc_dir, {
133 'A/B/E' : Item(status='D '),
134 'A/B/F' : Item(status='D '),
135 'A/B/lambda' : Item(status='D '),
136 'A/B/pi' : Item(status='A '),
137 'A/B/tau' : Item(status='A '),
138 'A/B/rho' : Item(status='A '),
141 # Create expected disk tree (iota will have gamma's contents,
142 # A/B/* will look like A/D/G/*)
143 expected_disk = get_routine_disk_state(wc_dir)
145 # Create expected status
146 expected_status = get_routine_status_state(wc_dir)
147 expected_status.tweak('iota', 'A/B', switched='S')
149 # Do the switch and check the results in three ways.
150 svntest.actions.run_and_verify_switch(wc_dir, AB_path, ADG_url,
151 expected_output,
152 expected_disk,
153 expected_status)
154 else:
155 svntest.main.run_svn(None,
156 'switch', ADG_url, AB_path)
159 #----------------------------------------------------------------------
161 def commit_routine_switching(wc_dir, verify):
162 "Commit some stuff in a routinely-switched working copy."
164 # Make some local mods
165 iota_path = os.path.join(wc_dir, 'iota')
166 Bpi_path = os.path.join(wc_dir, 'A', 'B', 'pi')
167 Gpi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi')
168 Z_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z')
169 zeta_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z', 'zeta')
171 svntest.main.file_append(iota_path, "apple")
172 svntest.main.file_append(Bpi_path, "melon")
173 svntest.main.file_append(Gpi_path, "banana")
174 os.mkdir(Z_path)
175 svntest.main.file_append(zeta_path, "This is the file 'zeta'.\n")
176 svntest.main.run_svn(None, 'add', Z_path)
178 # Try to commit. We expect this to fail because, if all the
179 # switching went as expected, A/B/pi and A/D/G/pi point to the
180 # same URL. We don't allow this.
181 svntest.actions.run_and_verify_commit(
182 wc_dir, None, None,
183 "svn: Cannot commit both .* as they refer to the same URL$",
184 wc_dir)
186 # Okay, that all taken care of, let's revert the A/D/G/pi path and
187 # move along. Afterward, we should be okay to commit. (Sorry,
188 # holsta, that banana has to go...)
189 svntest.main.run_svn(None, 'revert', Gpi_path)
191 # Create expected output tree.
192 expected_output = svntest.wc.State(wc_dir, {
193 'A/D/G/Z' : Item(verb='Adding'),
194 'A/D/G/Z/zeta' : Item(verb='Adding'),
195 'iota' : Item(verb='Sending'),
196 'A/B/pi' : Item(verb='Sending'),
199 # Created expected status tree.
200 expected_status = get_routine_status_state(wc_dir)
201 expected_status.tweak('iota', 'A/B', switched='S')
202 expected_status.tweak('iota', 'A/B/pi', wc_rev=2, status=' ')
203 expected_status.add({
204 'A/D/G/Z' : Item(status=' ', wc_rev=2),
205 'A/D/G/Z/zeta' : Item(status=' ', wc_rev=2),
208 # Commit should succeed
209 if verify:
210 svntest.actions.run_and_verify_commit(wc_dir,
211 expected_output,
212 expected_status,
213 None, wc_dir)
214 else:
215 svntest.main.run_svn(None,
216 'ci', '-m', 'log msg', wc_dir)
219 ######################################################################
220 # Tests
223 #----------------------------------------------------------------------
225 def routine_switching(sbox):
226 "test some basic switching operations"
228 sbox.build(read_only = True)
230 # Setup (and verify) some switched things
231 do_routine_switching(sbox.wc_dir, sbox.repo_url, 1)
234 #----------------------------------------------------------------------
236 def commit_switched_things(sbox):
237 "commits after some basic switching operations"
239 sbox.build()
240 wc_dir = sbox.wc_dir
242 # Setup some switched things (don't bother verifying)
243 do_routine_switching(wc_dir, sbox.repo_url, 0)
245 # Commit some stuff (and verify)
246 commit_routine_switching(wc_dir, 1)
249 #----------------------------------------------------------------------
251 def full_update(sbox):
252 "update wc that contains switched things"
254 sbox.build()
255 wc_dir = sbox.wc_dir
257 # Setup some switched things (don't bother verifying)
258 do_routine_switching(wc_dir, sbox.repo_url, 0)
260 # Copy wc_dir to a backup location
261 wc_backup = sbox.add_wc_path('backup')
262 svntest.actions.duplicate_dir(wc_dir, wc_backup)
264 # Commit some stuff (don't bother verifying)
265 commit_routine_switching(wc_backup, 0)
267 # Some convenient path variables
268 iota_path = os.path.join(wc_dir, 'iota')
269 gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
270 Bpi_path = os.path.join(wc_dir, 'A', 'B', 'pi')
271 BZ_path = os.path.join(wc_dir, 'A', 'B', 'Z')
272 Bzeta_path = os.path.join(wc_dir, 'A', 'B', 'Z', 'zeta')
273 Gpi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi')
274 GZ_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z')
275 Gzeta_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z', 'zeta')
277 # Create expected output tree for an update of wc_backup.
278 expected_output = svntest.wc.State(wc_dir, {
279 'iota' : Item(status='U '),
280 'A/D/gamma' : Item(status='U '),
281 'A/B/pi' : Item(status='U '),
282 'A/B/Z' : Item(status='A '),
283 'A/B/Z/zeta' : Item(status='A '),
284 'A/D/G/pi' : Item(status='U '),
285 'A/D/G/Z' : Item(status='A '),
286 'A/D/G/Z/zeta' : Item(status='A '),
289 # Create expected disk tree for the update
290 expected_disk = get_routine_disk_state(wc_dir)
291 expected_disk.tweak('iota', contents="This is the file 'gamma'.\napple")
292 expected_disk.tweak('A/D/gamma', contents="This is the file 'gamma'.\napple")
293 expected_disk.tweak('A/B/pi', contents="This is the file 'pi'.\nmelon")
294 expected_disk.tweak('A/D/G/pi', contents="This is the file 'pi'.\nmelon")
295 expected_disk.add({
296 'A/B/Z' : Item(),
297 'A/B/Z/zeta' : Item(contents="This is the file 'zeta'.\n"),
298 'A/D/G/Z' : Item(),
299 'A/D/G/Z/zeta' : Item(contents="This is the file 'zeta'.\n"),
302 # Create expected status tree for the update.
303 expected_status = get_routine_status_state(wc_dir)
304 expected_status.tweak(wc_rev=2)
305 expected_status.add({
306 'A/D/G/Z' : Item(status=' ', wc_rev=2),
307 'A/D/G/Z/zeta' : Item(status=' ', wc_rev=2),
308 'A/B/Z' : Item(status=' ', wc_rev=2),
309 'A/B/Z/zeta' : Item(status=' ', wc_rev=2),
311 expected_status.tweak('iota', 'A/B', switched='S')
313 svntest.actions.run_and_verify_update(wc_dir,
314 expected_output,
315 expected_disk,
316 expected_status)
318 #----------------------------------------------------------------------
320 def full_rev_update(sbox):
321 "reverse update wc that contains switched things"
323 sbox.build()
324 wc_dir = sbox.wc_dir
326 # Setup some switched things (don't bother verifying)
327 do_routine_switching(wc_dir, sbox.repo_url, 0)
329 # Commit some stuff (don't bother verifying)
330 commit_routine_switching(wc_dir, 0)
332 # Update to HEAD (tested elsewhere)
333 svntest.main.run_svn(None, 'up', wc_dir)
335 # Some convenient path variables
336 iota_path = os.path.join(wc_dir, 'iota')
337 gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
338 Bpi_path = os.path.join(wc_dir, 'A', 'B', 'pi')
339 BZ_path = os.path.join(wc_dir, 'A', 'B', 'Z')
340 Gpi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi')
341 GZ_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z')
343 # Now, reverse update, back to the pre-commit state.
344 expected_output = svntest.wc.State(wc_dir, {
345 'iota' : Item(status='U '),
346 'A/D/gamma' : Item(status='U '),
347 'A/B/pi' : Item(status='U '),
348 'A/B/Z' : Item(status='D '),
349 'A/D/G/pi' : Item(status='U '),
350 'A/D/G/Z' : Item(status='D '),
353 # Create expected disk tree
354 expected_disk = get_routine_disk_state(wc_dir)
356 # Create expected status
357 expected_status = get_routine_status_state(wc_dir)
358 expected_status.tweak('iota', 'A/B', switched='S')
360 svntest.actions.run_and_verify_update(wc_dir,
361 expected_output,
362 expected_disk,
363 expected_status,
364 None, None, None,
365 None, None, 1,
366 '-r', '1', wc_dir)
368 #----------------------------------------------------------------------
370 def update_switched_things(sbox):
371 "update switched wc things to HEAD"
373 sbox.build()
374 wc_dir = sbox.wc_dir
376 # Setup some switched things (don't bother verifying)
377 do_routine_switching(wc_dir, sbox.repo_url, 0)
379 # Copy wc_dir to a backup location
380 wc_backup = sbox.add_wc_path('backup')
381 svntest.actions.duplicate_dir(wc_dir, wc_backup)
383 # Commit some stuff (don't bother verifying)
384 commit_routine_switching(wc_backup, 0)
386 # Some convenient path variables
387 iota_path = os.path.join(wc_dir, 'iota')
388 B_path = os.path.join(wc_dir, 'A', 'B')
390 # Create expected output tree for an update of wc_backup.
391 expected_output = svntest.wc.State(wc_dir, {
392 'iota' : Item(status='U '),
393 'A/B/pi' : Item(status='U '),
394 'A/B/Z' : Item(status='A '),
395 'A/B/Z/zeta' : Item(status='A '),
398 # Create expected disk tree for the update
399 expected_disk = get_routine_disk_state(wc_dir)
400 expected_disk.tweak('iota', contents="This is the file 'gamma'.\napple")
402 expected_disk.tweak('A/B/pi', contents="This is the file 'pi'.\nmelon")
403 expected_disk.add({
404 'A/B/Z' : Item(),
405 'A/B/Z/zeta' : Item("This is the file 'zeta'.\n"),
408 # Create expected status tree for the update.
409 expected_status = get_routine_status_state(wc_dir)
410 expected_status.tweak('iota', 'A/B', switched='S')
411 expected_status.tweak('A/B', 'A/B/pi', 'A/B/rho', 'A/B/tau', 'iota',
412 wc_rev=2)
413 expected_status.add({
414 'A/B/Z' : Item(status=' ', wc_rev=2),
415 'A/B/Z/zeta' : Item(status=' ', wc_rev=2),
418 svntest.actions.run_and_verify_update(wc_dir,
419 expected_output,
420 expected_disk,
421 expected_status,
422 None, None, None,
423 None, None, 0,
424 B_path,
425 iota_path)
428 #----------------------------------------------------------------------
430 def rev_update_switched_things(sbox):
431 "reverse update switched wc things to an older rev"
433 sbox.build()
434 wc_dir = sbox.wc_dir
436 # Setup some switched things (don't bother verifying)
437 do_routine_switching(wc_dir, sbox.repo_url, 0)
439 # Commit some stuff (don't bother verifying)
440 commit_routine_switching(wc_dir, 0)
442 # Some convenient path variables
443 iota_path = os.path.join(wc_dir, 'iota')
444 B_path = os.path.join(wc_dir, 'A', 'B')
446 # Update to HEAD (tested elsewhere)
447 svntest.main.run_svn(None, 'up', wc_dir)
449 # Now, reverse update, back to the pre-commit state.
450 expected_output = svntest.wc.State(wc_dir, {
451 'iota' : Item(status='U '),
452 'A/B/pi' : Item(status='U '),
453 'A/B/Z' : Item(status='D '),
456 # Create expected disk tree
457 expected_disk = get_routine_disk_state(wc_dir)
458 expected_disk.tweak('A/D/gamma', contents="This is the file 'gamma'.\napple")
459 expected_disk.tweak('A/D/G/pi', contents="This is the file 'pi'.\nmelon")
460 expected_disk.add({
461 'A/D/G/Z' : Item(),
462 'A/D/G/Z/zeta' : Item("This is the file 'zeta'.\n"),
465 # Create expected status tree for the update.
466 expected_status = get_routine_status_state(wc_dir)
467 expected_status.tweak(wc_rev=2)
468 expected_status.tweak('iota', 'A/B', switched='S')
469 expected_status.tweak('A/B', 'A/B/pi', 'A/B/rho', 'A/B/tau', 'iota',
470 wc_rev=1)
471 expected_status.add({
472 'A/D/G/Z' : Item(status=' ', wc_rev=2),
473 'A/D/G/Z/zeta' : Item(status=' ', wc_rev=2),
476 svntest.actions.run_and_verify_update(wc_dir,
477 expected_output,
478 expected_disk,
479 expected_status,
480 None, None, None,
481 None, None, 1,
482 '-r', '1',
483 B_path,
484 iota_path)
487 #----------------------------------------------------------------------
489 def log_switched_file(sbox):
490 "show logs for a switched file"
492 sbox.build()
493 wc_dir = sbox.wc_dir
495 # Setup some switched things (don't bother verifying)
496 do_routine_switching(wc_dir, sbox.repo_url, 0)
498 # edit and commit switched file 'iota'
499 iota_path = os.path.join(wc_dir, 'iota')
500 svntest.main.run_svn(None, 'ps', 'x', 'x', iota_path)
501 svntest.main.run_svn(None,
502 'ci', '-m',
503 'set prop on switched iota',
504 iota_path)
506 # log switched file 'iota'
507 output, error = svntest.main.run_svn(None, 'log', iota_path)
508 for line in output:
509 if line.find("set prop on switched iota") != -1:
510 break
511 else:
512 raise svntest.Failure
514 #----------------------------------------------------------------------
516 def relocate_deleted_missing_copied(sbox):
517 "relocate with deleted, missing and copied entries"
518 sbox.build()
519 wc_dir = sbox.wc_dir
521 # Delete A/mu to create a deleted entry for mu in A/.svn/entries
522 mu_path = os.path.join(wc_dir, 'A', 'mu')
523 svntest.actions.run_and_verify_svn(None, None, [], 'rm', mu_path)
524 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
525 expected_status.remove('A/mu')
526 expected_output = svntest.wc.State(wc_dir, {
527 'A/mu' : Item(verb='Deleting'),
529 svntest.actions.run_and_verify_commit(wc_dir,
530 expected_output,
531 expected_status,
532 None, wc_dir)
534 # Remove A/B/F to create a missing entry
535 svntest.main.safe_rmtree(os.path.join(wc_dir, 'A', 'B', 'F'))
537 # Copy A/D/H to A/D/H2
538 H_path = os.path.join(wc_dir, 'A', 'D', 'H')
539 H2_path = os.path.join(wc_dir, 'A', 'D', 'H2')
540 svntest.actions.run_and_verify_svn(None, None, [], 'copy',
541 H_path, H2_path)
542 expected_status.add({
543 'A/D/H2' : Item(status='A ', wc_rev='-', copied='+'),
544 'A/D/H2/chi' : Item(status=' ', wc_rev='-', copied='+'),
545 'A/D/H2/omega' : Item(status=' ', wc_rev='-', copied='+'),
546 'A/D/H2/psi' : Item(status=' ', wc_rev='-', copied='+'),
548 expected_status.tweak('A/B/F', status='! ', wc_rev='?')
549 svntest.actions.run_and_verify_status(wc_dir, expected_status)
551 # Relocate
552 repo_dir = sbox.repo_dir
553 repo_url = sbox.repo_url
554 other_repo_dir, other_repo_url = sbox.add_repo_path('other')
555 svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 0)
556 svntest.main.safe_rmtree(repo_dir, 1)
557 svntest.actions.run_and_verify_svn(None, None, [], 'switch', '--relocate',
558 repo_url, other_repo_url, wc_dir)
560 # Deleted and missing entries should be preserved, so update should
561 # show only A/B/F being reinstated
562 expected_output = svntest.wc.State(wc_dir, {
563 'A/B/F' : Item(status='A '),
565 expected_disk = svntest.main.greek_state.copy()
566 expected_disk.remove('A/mu')
567 expected_disk.add({
568 'A/D/H2' : Item(),
569 'A/D/H2/chi' : Item("This is the file 'chi'.\n"),
570 'A/D/H2/omega' : Item("This is the file 'omega'.\n"),
571 'A/D/H2/psi' : Item("This is the file 'psi'.\n"),
573 expected_status.add({
574 'A/B/F' : Item(status=' ', wc_rev='2'),
576 expected_status.tweak(wc_rev=2)
577 expected_status.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi',
578 wc_rev='-')
579 svntest.actions.run_and_verify_update(wc_dir,
580 expected_output,
581 expected_disk,
582 expected_status)
584 # Commit to verify that copyfrom URLs have been relocated
585 expected_output = svntest.wc.State(wc_dir, {
586 'A/D/H2' : Item(verb='Adding'),
588 expected_status.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi',
589 status=' ', wc_rev='3', copied=None)
590 svntest.actions.run_and_verify_commit(wc_dir,
591 expected_output, expected_status,
592 None, wc_dir)
595 #----------------------------------------------------------------------
597 def delete_subdir(sbox):
598 "switch that deletes a sub-directory"
599 sbox.build()
600 wc_dir = sbox.wc_dir
602 A_path = os.path.join(wc_dir, 'A')
603 A_url = sbox.repo_url + '/A'
604 A2_url = sbox.repo_url + '/A2'
605 A2_B_F_url = sbox.repo_url + '/A2/B/F'
607 svntest.actions.run_and_verify_svn(None,
608 ['\n', 'Committed revision 2.\n'], [],
609 'cp', '-m', 'make copy', A_url, A2_url)
611 svntest.actions.run_and_verify_svn(None,
612 ['\n', 'Committed revision 3.\n'], [],
613 'rm', '-m', 'delete subdir', A2_B_F_url)
615 expected_output = svntest.wc.State(wc_dir, {
616 'A/B/F' : Item(status='D '),
618 expected_disk = svntest.main.greek_state.copy()
619 expected_disk.remove('A/B/F')
620 expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
621 expected_status.tweak('A', switched='S')
622 expected_status.remove('A/B/F')
623 expected_status.tweak('', 'iota', wc_rev=1)
625 # Used to fail with a 'directory not locked' error for A/B/F
626 svntest.actions.run_and_verify_switch(wc_dir, A_path, A2_url,
627 expected_output,
628 expected_disk,
629 expected_status)
631 #----------------------------------------------------------------------
632 # Issue 1532: Switch a file to a dir: can't switch it back to the file
634 def file_dir_file(sbox):
635 "switch a file to a dir and back to the file"
636 sbox.build(read_only = True)
637 wc_dir = sbox.wc_dir
639 file_path = os.path.join(wc_dir, 'iota')
640 file_url = sbox.repo_url + '/iota'
641 dir_url = sbox.repo_url + '/A/C'
643 svntest.actions.run_and_verify_svn(None, None, [],
644 'switch', dir_url, file_path)
646 svntest.actions.run_and_verify_svn(None, None, [],
647 'switch', file_url, file_path)
649 #----------------------------------------------------------------------
650 # Issue 1751: "svn switch --non-recursive" does not switch existing files,
651 # and generates the wrong URL for new files.
653 def nonrecursive_switching(sbox):
654 "non-recursive switch"
655 sbox.build()
656 wc1_dir = sbox.wc_dir
657 wc2_dir = os.path.join(wc1_dir, 'wc2')
659 # "Trunk" will be the existing dir "A/", with existing file "mu".
660 # "Branch" will be the new dir "branch/version1/", with added file "newfile".
661 # "wc1" will hold the whole repository (including trunk and branch).
662 # "wc2" will hold the "trunk" and then be switched to the "branch".
663 # It is irrelevant that wc2 is located on disk as a sub-directory of wc1.
664 trunk_url = sbox.repo_url + '/A'
665 branch_url = sbox.repo_url + '/branch'
666 version1_url = branch_url + '/version1'
667 wc1_new_file = os.path.join(wc1_dir, 'branch', 'version1', 'newfile')
668 wc2_new_file = os.path.join(wc2_dir, 'newfile')
669 wc2_mu_file = os.path.join(wc2_dir, 'mu')
670 wc2_B_dir = os.path.join(wc2_dir, 'B')
671 wc2_C_dir = os.path.join(wc2_dir, 'C')
672 wc2_D_dir = os.path.join(wc2_dir, 'D')
674 # Check out the trunk as "wc2"
675 svntest.main.run_svn(None, 'co', trunk_url, wc2_dir)
677 # Make a branch, and add a new file, in "wc_dir" and repository
678 svntest.main.run_svn(None,
679 'mkdir', '-m', '', branch_url)
680 svntest.main.run_svn(None,
681 'cp', '-m', '', trunk_url, version1_url)
682 svntest.main.run_svn(None,
683 'up', wc1_dir)
684 svntest.main.file_append(wc1_new_file, "This is the file 'newfile'.\n")
685 svntest.main.run_svn(None, 'add', wc1_new_file)
686 svntest.main.run_svn(None, 'ci', '-m', '', wc1_dir)
688 # Try to switch "wc2" to the branch (non-recursively)
689 svntest.actions.run_and_verify_svn(None, None, [],
690 'switch', '-N', version1_url, wc2_dir)
692 # Check the URLs of the (not switched) directories.
693 out, err = svntest.actions.run_and_verify_svn(None, None, [],
694 'info', wc2_B_dir)
695 if out[1].find('/A/B') == -1:
696 print out[1]
697 raise svntest.Failure
699 out, err = svntest.actions.run_and_verify_svn(None, None, [],
700 'info', wc2_C_dir)
701 if out[1].find('/A/C') == -1:
702 print out[1]
703 raise svntest.Failure
705 out, err = svntest.actions.run_and_verify_svn(None, None, [],
706 'info', wc2_D_dir)
707 if out[1].find('/A/D') == -1:
708 print out[1]
709 raise svntest.Failure
711 # Check the URLs of the switched files.
712 # ("svn status -u" might be a better check: it fails when newfile's URL
713 # is bad, and shows "S" when mu's URL is wrong.)
714 # mu: not switched
715 out, err = svntest.actions.run_and_verify_svn(None, None, [],
716 'info', wc2_mu_file)
717 if out[2].find('/branch/version1/mu') == -1:
718 print out[2]
719 raise svntest.Failure
720 # newfile: wrong URL
721 out, err = svntest.actions.run_and_verify_svn(None, None, [],
722 'info', wc2_new_file)
723 if out[2].find('/branch/version1/newfile') == -1:
724 print out[2]
725 raise svntest.Failure
728 #----------------------------------------------------------------------
729 def failed_anchor_is_target(sbox):
730 "anchor=target that fails due to local mods"
731 sbox.build()
732 wc_dir = sbox.wc_dir
734 G_url = sbox.repo_url + '/A/D/G'
735 G_psi_url = G_url + '/psi'
736 svntest.actions.run_and_verify_svn(None,
737 ['\n', 'Committed revision 2.\n'], [],
738 'mkdir', '-m', 'log msg', G_psi_url)
740 H_path = os.path.join(wc_dir, 'A', 'D', 'H')
741 psi_path = os.path.join(H_path, 'psi')
742 svntest.main.file_append(psi_path, "more text")
744 # This switch leaves psi unversioned, because of the local mods,
745 # then fails because it tries to add a directory of the same name.
746 out, err = svntest.main.run_svn(1, 'switch',
747 G_url, H_path)
748 if not err:
749 raise svntest.Failure
751 # Some items under H show up as switched because, while H itself was
752 # switched, the switch command failed before it reached all items
754 # NOTE: I suspect this whole test is dependent on the order in
755 # which changes are received, but since the new psi is a dir, it
756 # appears we can count on it being received last. But if this test
757 # ever starts failing, you read it here first :-).
758 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
759 expected_status.tweak('A/D/H', status='! ', switched='S', wc_rev=2)
760 expected_status.remove('A/D/H/psi', 'A/D/H/chi', 'A/D/H/omega')
761 expected_status.add({
762 'A/D/H/pi' : Item(status=' ', wc_rev=2),
763 'A/D/H/tau' : Item(status=' ', wc_rev=2),
764 'A/D/H/rho' : Item(status=' ', wc_rev=2),
766 svntest.actions.run_and_verify_status(wc_dir, expected_status)
768 # There was a bug whereby the failed switch left the wrong URL in
769 # the target directory H. Check for that.
770 out, err = svntest.actions.run_and_verify_svn(None, None, [], 'info', H_path)
771 for line in out:
772 if line.find('URL: ' + G_url) != -1:
773 break
774 else:
775 raise svntest.Failure
777 # Remove the now-unversioned psi, and repeat the switch. This
778 # should complete the switch.
779 os.remove(psi_path)
780 svntest.actions.run_and_verify_svn(None, None, [], 'switch',
781 G_url, H_path)
783 expected_status.tweak('A/D/H', status=' ') # remains switched
784 expected_status.add({ 'A/D/H/psi' : Item(status=' ',
785 switched=None,
786 wc_rev=2) })
787 svntest.actions.run_and_verify_status(wc_dir, expected_status)
789 #----------------------------------------------------------------------
790 # Issue #1826 - svn switch temporarily drops invalid URLs into the entries
791 # files (which become not-temporary if the switch fails).
792 def bad_intermediate_urls(sbox):
793 "bad intermediate urls in use"
794 sbox.build()
795 wc_dir = sbox.wc_dir
797 # We'll be switching our working copy to (a modified) A/C in the Greek tree.
799 # First, make an extra subdirectory in C to match one in the root, plus
800 # another one inside of that.
801 C_url = sbox.repo_url + '/A/C'
802 C_A_url = sbox.repo_url + '/A/C/A'
803 C_A_Z_url = sbox.repo_url + '/A/C/A/Z'
804 svntest.actions.run_and_verify_svn(None,
805 ['\n', 'Committed revision 2.\n'], [],
806 'mkdir', '-m', 'log msg',
807 C_A_url, C_A_Z_url)
809 # Now, we'll drop a conflicting path under the root.
810 A_path = os.path.join(wc_dir, 'A')
811 A_Z_path = os.path.join(A_path, 'Z')
812 svntest.main.file_append(A_Z_path, 'Look, Mom, no ... switch success.')
814 # This switch should fail for reasons of obstruction.
815 out, err = svntest.main.run_svn(1, 'switch',
816 C_url, wc_dir)
817 if not err:
818 raise svntest.Failure
820 # However, the URL for A should now reflect A/C/A, not something else.
821 out, err = svntest.actions.run_and_verify_svn(None, None, [],
822 'info', A_path)
823 if out[1].find('/A/C/A') == -1:
824 raise svntest.Failure
828 #----------------------------------------------------------------------
829 # Regression test for issue #1825: failed switch may corrupt
830 # working copy
832 def obstructed_switch(sbox):
833 "obstructed switch"
834 sbox.build()
835 wc_dir = sbox.wc_dir
837 E_url = sbox.repo_url + '/A/B/E'
838 E_url2 = sbox.repo_url + '/A/B/Esave'
839 svntest.actions.run_and_verify_svn(None,
840 ['\n', 'Committed revision 2.\n'], [],
841 'cp', '-m', 'msgcopy', E_url, E_url2)
843 E_path = os.path.join(wc_dir, 'A', 'B', 'E')
844 alpha_path = os.path.join(E_path, 'alpha')
845 svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
846 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
847 expected_status.remove('A/B/E/alpha')
848 expected_output = svntest.wc.State(wc_dir, {
849 'A/B/E/alpha' : Item(verb='Deleting'),
851 svntest.actions.run_and_verify_commit(wc_dir,
852 expected_output, expected_status,
853 None, wc_dir)
855 svntest.main.file_append(alpha_path, "hello")
856 out, err = svntest.main.run_svn(1,
857 'sw', E_url2, E_path)
858 for line in err:
859 if line.find("object of the same name already exists") != -1:
860 break
861 else:
862 raise svntest.Failure
864 os.remove(alpha_path)
865 svntest.actions.run_and_verify_svn(None, None, [], 'sw', E_url2, E_path)
866 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
867 expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', wc_rev=3)
868 expected_status.tweak('A/B/E', switched='S')
869 svntest.actions.run_and_verify_status(wc_dir, expected_status)
872 #----------------------------------------------------------------------
873 # Issue 2353.
874 def commit_mods_below_switch(sbox):
875 "commit with mods below switch"
876 sbox.build()
877 wc_dir = sbox.wc_dir
879 C_path = os.path.join(wc_dir, 'A', 'C')
880 B_url = sbox.repo_url + '/A/B'
881 expected_output = svntest.wc.State(wc_dir, {
882 'A/C/E' : Item(status='A '),
883 'A/C/E/alpha' : Item(status='A '),
884 'A/C/E/beta' : Item(status='A '),
885 'A/C/F' : Item(status='A '),
886 'A/C/lambda' : Item(status='A '),
888 expected_disk = svntest.main.greek_state.copy()
889 expected_disk.add({
890 'A/C/E' : Item(),
891 'A/C/E/alpha' : Item(contents="This is the file 'alpha'.\n"),
892 'A/C/E/beta' : Item(contents="This is the file 'beta'.\n"),
893 'A/C/F' : Item(),
894 'A/C/lambda' : Item(contents="This is the file 'lambda'.\n"),
896 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
897 expected_status.tweak('A/C', switched='S')
898 expected_status.add({
899 'A/C/E' : Item(status=' ', wc_rev=1),
900 'A/C/E/alpha' : Item(status=' ', wc_rev=1),
901 'A/C/E/beta' : Item(status=' ', wc_rev=1),
902 'A/C/F' : Item(status=' ', wc_rev=1),
903 'A/C/lambda' : Item(status=' ', wc_rev=1),
905 svntest.actions.run_and_verify_switch(wc_dir, C_path, B_url,
906 expected_output,
907 expected_disk,
908 expected_status)
910 D_path = os.path.join(wc_dir, 'A', 'D')
911 svntest.actions.run_and_verify_svn(None, None, [],
912 'propset', 'x', 'x', C_path, D_path)
914 expected_status.tweak('A/C', 'A/D', status=' M')
915 svntest.actions.run_and_verify_status(wc_dir, expected_status)
917 expected_output = svntest.wc.State(wc_dir, {
918 'A/C' : Item(verb='Sending'),
919 'A/D' : Item(verb='Sending'),
921 expected_status.tweak('A/C', 'A/D', status=' ', wc_rev=2)
923 # A/C erroneously classified as a wc root caused the commit to fail
924 # with "'A/C/E' is missing or not locked"
925 svntest.actions.run_and_verify_commit(wc_dir,
926 expected_output, expected_status,
927 None, C_path, D_path)
929 def relocate_beyond_repos_root(sbox):
930 "relocate with prefixes longer than repo root"
931 sbox.build(read_only = True)
933 wc_dir = sbox.wc_dir
934 repo_dir = sbox.repo_dir
935 repo_url = sbox.repo_url
936 other_repo_dir, other_repo_url = sbox.add_repo_path('other')
937 svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0)
939 A_url = repo_url + "/A"
940 other_A_url = other_repo_url + "/A"
941 other_B_url = other_repo_url + "/B"
942 A_wc_dir = os.path.join(wc_dir, "A")
944 # A relocate that changes the repo path part of the URL shouldn't work.
945 # This tests for issue #2380.
946 svntest.actions.run_and_verify_svn(None, None,
947 ".*can only change the repository part.*",
948 'switch', '--relocate',
949 A_url, other_B_url, A_wc_dir)
951 # Another way of trying to change the fs path, leading to an invalid
952 # repository root.
953 svntest.actions.run_and_verify_svn(None, None,
954 ".*is not the root.*",
955 'switch', '--relocate',
956 repo_url, other_B_url, A_wc_dir)
958 svntest.actions.run_and_verify_svn(None, None, [],
959 'switch', '--relocate',
960 A_url, other_A_url, A_wc_dir)
962 # Check that we can contact the repository, meaning that the
963 # relocate actually changed the URI. Escape the expected URI to
964 # avoid problems from any regex meta-characters it may contain
965 # (e.g. '+').
966 escaped_exp = '^URL: ' + re.escape(other_A_url) + '$' \
967 '|Path.+|Repository.+|Revision.+|Node.+|Last.+|\n'
968 svntest.actions.run_and_verify_svn(None, escaped_exp, [],
969 'info', '-rHEAD', A_wc_dir)
971 #----------------------------------------------------------------------
972 # Issue 2306.
973 def refresh_read_only_attribute(sbox):
974 "refresh the WC file system read-only attribute "
976 # This test will fail when run as root. Since that's normal
977 # behavior, just skip the test.
978 if os.name == 'posix':
979 if os.geteuid() == 0:
980 raise svntest.Skip
982 sbox.build()
983 wc_dir = sbox.wc_dir
985 # Create a branch.
986 url = sbox.repo_url + '/A'
987 branch_url = sbox.repo_url + '/A-branch'
988 svntest.actions.run_and_verify_svn(None,
989 ['\n', 'Committed revision 2.\n'], [],
990 'cp', '-m', 'svn:needs-lock not set',
991 url, branch_url)
993 # Set the svn:needs-lock property on a file from the "trunk".
994 A_path = os.path.join(wc_dir, 'A')
995 mu_path = os.path.join(A_path, 'mu')
996 svntest.actions.run_and_verify_svn(None, None, [],
997 'ps', 'svn:needs-lock', '1', mu_path)
999 # Commit the propset of svn:needs-lock.
1000 expected_output = svntest.wc.State(wc_dir, {
1001 'A/mu' : Item(verb='Sending'),
1003 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1004 expected_status.tweak('A/mu', wc_rev=3)
1005 svntest.actions.run_and_verify_commit(wc_dir,
1006 expected_output, expected_status,
1007 None, mu_path)
1009 # The file on which svn:needs-lock was set is now expected to be read-only.
1010 if os.access(mu_path, os.W_OK):
1011 raise svntest.Failure("'%s' expected to be read-only after having had "
1012 "its svn:needs-lock property set" % mu_path)
1014 # Switch to the branch with the WC state from before the propset of
1015 # svn:needs-lock.
1016 expected_output = svntest.wc.State(wc_dir, {
1017 'A/mu' : Item(status=' U'),
1019 expected_disk = svntest.main.greek_state.copy()
1020 expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
1021 expected_status.tweak('', wc_rev=1)
1022 expected_status.tweak('iota', wc_rev=1)
1023 expected_status.tweak('A', switched='S')
1024 svntest.actions.run_and_verify_switch(wc_dir, A_path, branch_url,
1025 expected_output,
1026 expected_disk,
1027 expected_status)
1029 # The file with we set svn:needs-lock on should now be writable, but
1030 # is still read-only!
1031 if not os.access(mu_path, os.W_OK):
1032 raise svntest.Failure("'%s' expected to be writable after being switched "
1033 "to a branch on which its svn:needs-lock property "
1034 "is not set" % mu_path)
1036 # Check that switch can't change the repository root.
1037 def switch_change_repos_root(sbox):
1038 "switch shouldn't allow changing repos root"
1039 sbox.build()
1041 wc_dir = sbox.wc_dir
1042 repo_url = sbox.repo_url
1043 other_repo_url = repo_url
1045 # Strip trailing slashes and add something bogus to that other URL.
1046 while other_repo_url[-1] == '/':
1047 other_repos_url = other_repo_url[:-1]
1048 other_repo_url = other_repo_url + "_bogus"
1050 other_A_url = other_repo_url + "/A"
1051 A_wc_dir = os.path.join(wc_dir, "A")
1053 # Test 1: A switch that changes to a non-existing repo shouldn't work.
1054 expected_err = ".*Unable to open repository.*|.*Could not open.*|"\
1055 ".*No repository found.*"
1056 svntest.actions.run_and_verify_svn(None, None,
1057 expected_err,
1058 'switch',
1059 other_A_url, A_wc_dir)
1061 # Test 2: A switch that changes the repo root part of the URL shouldn't work.
1062 other_repo_dir, other_repo_url = sbox.add_repo_path('other')
1063 other_A_url = other_repo_url + "/A"
1065 svntest.main.create_repos(other_repo_dir)
1066 svntest.actions.run_and_verify_svn(None, None,
1067 ".*not the same repository.*",
1068 'switch',
1069 other_A_url, A_wc_dir)
1071 # Make sure we didn't break the WC.
1072 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1073 svntest.actions.run_and_verify_status(wc_dir, expected_status)
1075 # Issue 2578.
1076 def relocate_and_propset(sbox):
1077 "out of date propset should fail after a relocate"
1079 # Create virgin repos and working copy
1080 svntest.main.safe_rmtree(sbox.repo_dir, 1)
1081 svntest.main.create_repos(sbox.repo_dir)
1083 wc_dir = sbox.wc_dir
1084 repo_dir = sbox.repo_dir
1085 repo_url = sbox.repo_url
1087 # import the greek tree
1088 svntest.main.greek_state.write_to_disk(svntest.main.greek_dump_dir)
1089 output, errput = svntest.main.run_svn(None, 'import',
1090 '-m', 'Log message for revision 1.',
1091 svntest.main.greek_dump_dir, sbox.repo_url)
1093 # checkout
1094 svntest.main.safe_rmtree(wc_dir, 1)
1095 svntest.actions.run_and_verify_svn(None,
1096 None, [],
1097 'checkout',
1098 repo_url, wc_dir)
1100 # Relocate
1101 other_repo_dir, other_repo_url = sbox.add_repo_path('other')
1102 svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0)
1103 svntest.main.safe_rmtree(repo_dir, 1)
1104 svntest.actions.run_and_verify_svn(None, None, [], 'switch', '--relocate',
1105 repo_url, other_repo_url, wc_dir)
1107 # Remove gamma from the working copy.
1108 D_path = os.path.join(wc_dir, 'A', 'D')
1109 gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
1110 svntest.main.run_svn(None, 'rm', gamma_path)
1112 # Create expected commit output.
1113 expected_output = svntest.wc.State(wc_dir, {
1114 'A/D/gamma' : Item(verb='Deleting'),
1117 # After committing, status should show no sign of gamma.
1118 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1119 expected_status.remove('A/D/gamma')
1121 # Commit the deletion of gamma and verify.
1122 svntest.actions.run_and_verify_commit(wc_dir,
1123 expected_output,
1124 expected_status,
1125 None, wc_dir)
1127 # Now gamma should be marked as `deleted' under the hood, at
1128 # revision 2. Meanwhile, A/D is still lagging at revision 1.
1130 # Make a propchange on A/D
1131 svntest.main.run_svn(None, 'ps', 'foo', 'bar', D_path)
1133 # Commit and *expect* a repository Merge failure:
1134 svntest.actions.run_and_verify_commit(wc_dir,
1135 None,
1136 None,
1137 "[Oo]ut.of.date",
1138 wc_dir)
1140 #----------------------------------------------------------------------
1142 def forced_switch(sbox):
1143 "forced switch tolerates obstructions to adds"
1144 sbox.build(read_only = True)
1146 # Dir obstruction
1147 G_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G')
1148 os.mkdir(G_path)
1150 # Faux file obstructions
1151 shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'gamma'),
1152 os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'gamma'))
1153 shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'tau'),
1154 os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'tau'))
1156 # Real file obstruction
1157 pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'pi')
1158 svntest.main.file_write(pi_path,
1159 "This is the OBSTRUCTING file 'pi'.\n")
1161 # Non-obstructing dir and file
1162 I_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'I')
1163 os.mkdir(I_path)
1164 upsilon_path = os.path.join(G_path, 'upsilon')
1165 svntest.main.file_write(upsilon_path,
1166 "This is the unversioned file 'upsilon'.\n")
1168 # Setup expected results of switch.
1169 expected_output = svntest.wc.State(sbox.wc_dir, {
1170 "A/B/F/gamma" : Item(status='E '),
1171 "A/B/F/G" : Item(status='E '),
1172 "A/B/F/G/pi" : Item(status='E '),
1173 "A/B/F/G/rho" : Item(status='A '),
1174 "A/B/F/G/tau" : Item(status='E '),
1175 "A/B/F/H" : Item(status='A '),
1176 "A/B/F/H/chi" : Item(status='A '),
1177 "A/B/F/H/omega" : Item(status='A '),
1178 "A/B/F/H/psi" : Item(status='A '),
1180 expected_disk = svntest.main.greek_state.copy()
1181 expected_disk.add({
1182 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
1183 "A/B/F/G" : Item(),
1184 "A/B/F/G/pi" : Item("This is the OBSTRUCTING file 'pi'.\n"),
1185 "A/B/F/G/rho" : Item("This is the file 'rho'.\n"),
1186 "A/B/F/G/tau" : Item("This is the file 'tau'.\n"),
1187 "A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"),
1188 "A/B/F/H" : Item(),
1189 "A/B/F/H/chi" : Item("This is the file 'chi'.\n"),
1190 "A/B/F/H/omega" : Item("This is the file 'omega'.\n"),
1191 "A/B/F/H/psi" : Item("This is the file 'psi'.\n"),
1192 "A/B/F/I" : Item(),
1194 expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
1195 expected_status.tweak('A/B/F', switched='S')
1196 expected_status.add({
1197 "A/B/F/gamma" : Item(status=' ', wc_rev=1),
1198 "A/B/F/G" : Item(status=' ', wc_rev=1),
1199 "A/B/F/G/pi" : Item(status='M ', wc_rev=1),
1200 "A/B/F/G/rho" : Item(status=' ', wc_rev=1),
1201 "A/B/F/G/tau" : Item(status=' ', wc_rev=1),
1202 "A/B/F/H" : Item(status=' ', wc_rev=1),
1203 "A/B/F/H/chi" : Item(status=' ', wc_rev=1),
1204 "A/B/F/H/omega" : Item(status=' ', wc_rev=1),
1205 "A/B/F/H/psi" : Item(status=' ', wc_rev=1),
1208 # Do the switch and check the results in three ways.
1209 F_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F')
1210 AD_url = sbox.repo_url + '/A/D'
1211 svntest.actions.run_and_verify_switch(sbox.wc_dir, F_path, AD_url,
1212 expected_output,
1213 expected_disk,
1214 expected_status, None,
1215 None, None, None, None, 0,
1216 '--force')
1218 #----------------------------------------------------------------------
1220 def forced_switch_failures(sbox):
1221 "forced switch fails with some types of obstuctions"
1222 sbox.build()
1224 # Add a directory to obstruct a file.
1225 pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'pi')
1226 os.mkdir(pi_path)
1228 # Add a file to obstruct a directory.
1229 H_path = os.path.join(sbox.wc_dir, 'A', 'C', 'H')
1230 svntest.main.file_write(H_path, "The file 'H'\n")
1232 # Test three cases where forced switch should fail:
1234 # 1) A forced switch that tries to add a file when an unversioned
1235 # directory of the same name already exists should fail.
1236 svntest.actions.run_and_verify_switch(sbox.wc_dir,
1237 os.path.join(sbox.wc_dir, 'A', 'C'),
1238 sbox.repo_url + "/A/D",
1239 None, None, None,
1240 ".*Failed to add directory .*" + \
1241 ": a non-directory object of the" + \
1242 " same name already exists\n",
1243 None, None, None, None, 0, '--force')
1245 # 2) A forced switch that tries to add a dir when a file of the same
1246 # name already exists should fail.
1247 svntest.actions.run_and_verify_switch(sbox.wc_dir,
1248 os.path.join(sbox.wc_dir,
1249 'A', 'B', 'F'),
1250 sbox.repo_url + "/A/D/G",
1251 None, None, None,
1252 ".*Failed to add file .*" + \
1253 ": a non-file object of the " + \
1254 "same name already exists\n",
1255 None, None, None, None, 0, '--force')
1257 # 3) A forced update that tries to add a directory when a versioned
1258 # directory of the same name already exists should fail.
1260 # Make dir A/D/H/I in repos.
1261 I_url = sbox.repo_url + "/A/D/H/I"
1262 so, se = svntest.actions.run_and_verify_svn("Unexpected error during mkdir",
1263 ['\n', 'Committed revision 2.\n'],
1265 "mkdir", I_url,
1266 "-m", "Log Message")
1268 # Make A/D/G/I and co A/D/H/I into it.
1269 I_path = os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'I')
1270 os.mkdir(I_path)
1271 so, se = svntest.actions.run_and_verify_svn("Unexpected error during co",
1272 ['Checked out revision 2.\n'],
1274 "co", I_url, I_path)
1276 # Try the forced switch. A/D/G/I obstructs the dir A/D/G/I coming
1277 # from the repos. Normally this isn't a problem, but A/D/G/I is already
1278 # versioned so this should fail.
1279 svntest.actions.run_and_verify_switch(sbox.wc_dir,
1280 os.path.join(sbox.wc_dir,
1281 'A', 'D', 'G'),
1282 sbox.repo_url + "/A/D/H",
1283 None, None, None,
1284 ".*Failed to add " + \
1285 "directory .*: a versioned " + \
1286 "directory of the same name " + \
1287 "already exists\n",
1288 None, None, None, None, 0, '--force')
1290 def switch_with_obstructing_local_adds(sbox):
1291 "switch tolerates WC adds"
1292 sbox.build(read_only = True)
1294 # Dir obstruction scheduled for addition without history.
1295 G_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G')
1296 os.mkdir(G_path)
1298 # File obstructions scheduled for addition without history.
1299 # Contents identical to additions from switch.
1300 gamma_copy_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'gamma')
1301 shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'gamma'),
1302 gamma_copy_path)
1303 shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'tau'),
1304 os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'tau'))
1306 # File obstruction scheduled for addition without history.
1307 # Contents conflict with addition from switch.
1308 pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'pi')
1309 svntest.main.file_write(pi_path,
1310 "This is the OBSTRUCTING file 'pi'.\n")
1312 # Non-obstructing dir and file scheduled for addition without history.
1313 I_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'I')
1314 os.mkdir(I_path)
1315 upsilon_path = os.path.join(G_path, 'upsilon')
1316 svntest.main.file_write(upsilon_path,
1317 "This is the unversioned file 'upsilon'.\n")
1319 # Add the above obstructions.
1320 svntest.actions.run_and_verify_svn("Add error:", None, [],
1321 'add', G_path, I_path,
1322 gamma_copy_path)
1324 # Setup expected results of switch.
1325 expected_output = svntest.wc.State(sbox.wc_dir, {
1326 "A/B/F/gamma" : Item(status='E '),
1327 "A/B/F/G" : Item(status='E '),
1328 "A/B/F/G/pi" : Item(status='C '),
1329 "A/B/F/G/rho" : Item(status='A '),
1330 "A/B/F/G/tau" : Item(status='E '),
1331 "A/B/F/H" : Item(status='A '),
1332 "A/B/F/H/chi" : Item(status='A '),
1333 "A/B/F/H/omega" : Item(status='A '),
1334 "A/B/F/H/psi" : Item(status='A '),
1337 expected_disk = svntest.main.greek_state.copy()
1338 expected_disk.add({
1339 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
1340 "A/B/F/G" : Item(),
1341 "A/B/F/G/pi" : Item("\n".join(["<<<<<<< .mine",
1342 "This is the OBSTRUCTING file 'pi'.",
1343 "=======",
1344 "This is the file 'pi'.",
1345 ">>>>>>> .r1",
1346 ""])),
1347 "A/B/F/G/rho" : Item("This is the file 'rho'.\n"),
1348 "A/B/F/G/tau" : Item("This is the file 'tau'.\n"),
1349 "A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"),
1350 "A/B/F/H" : Item(),
1351 "A/B/F/H/chi" : Item("This is the file 'chi'.\n"),
1352 "A/B/F/H/omega" : Item("This is the file 'omega'.\n"),
1353 "A/B/F/H/psi" : Item("This is the file 'psi'.\n"),
1354 "A/B/F/I" : Item(),
1356 expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
1357 expected_status.tweak('A/B/F', switched='S')
1358 expected_status.add({
1359 "A/B/F/gamma" : Item(status=' ', wc_rev=1),
1360 "A/B/F/G" : Item(status=' ', wc_rev=1),
1361 "A/B/F/G/pi" : Item(status='C ', wc_rev=1),
1362 "A/B/F/G/rho" : Item(status=' ', wc_rev=1),
1363 "A/B/F/G/tau" : Item(status=' ', wc_rev=1),
1364 "A/B/F/G/upsilon" : Item(status='A ', wc_rev=0),
1365 "A/B/F/H" : Item(status=' ', wc_rev=1),
1366 "A/B/F/H/chi" : Item(status=' ', wc_rev=1),
1367 "A/B/F/H/omega" : Item(status=' ', wc_rev=1),
1368 "A/B/F/H/psi" : Item(status=' ', wc_rev=1),
1369 "A/B/F/I" : Item(status='A ', wc_rev=0),
1372 # "Extra" files that we expect to result from the conflicts.
1373 extra_files = ['pi\.r0', 'pi\.r1', 'pi\.mine']
1375 # Do the switch and check the results in three ways.
1376 F_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F')
1377 D_url = sbox.repo_url + '/A/D'
1379 svntest.actions.run_and_verify_switch(sbox.wc_dir, F_path, D_url,
1380 expected_output,
1381 expected_disk,
1382 expected_status,
1383 None,
1384 svntest.tree.detect_conflict_files,
1385 extra_files, None, None, 0)
1387 #----------------------------------------------------------------------
1389 def switch_scheduled_add(sbox):
1390 "switch a scheduled-add file"
1391 sbox.build(read_only = True)
1392 wc_dir = sbox.wc_dir
1394 file_path = os.path.join(wc_dir, 'stub_file')
1395 switch_url = sbox.repo_url + '/iota'
1397 svntest.main.file_append(file_path, "")
1398 svntest.actions.run_and_verify_svn(None, None, [],
1399 'add', file_path)
1400 svntest.actions.run_and_verify_svn(None, None, [],
1401 'switch', switch_url, file_path)
1403 #----------------------------------------------------------------------
1405 def mergeinfo_switch_elision(sbox):
1406 "mergeinfo does not elide post switch"
1408 # When a switch adds mergeinfo on a path which is identical to
1409 # the mergeinfo on one of the path's subtrees, the subtree's mergeinfo
1410 # should *not* elide! If it did this could result in the switch of a
1411 # pristine tree producing local mods.
1413 # Search for the comment entitled "The Merge Kluge" in merge_tests.py
1414 # to understand why we shorten, and subsequently chdir() after calling
1415 # this function.
1416 def shorten_path_kludge(path):
1417 shorten_by = len(svntest.main.work_dir) + len(os.sep)
1418 return path[shorten_by:]
1420 sbox.build()
1421 wc_dir = sbox.wc_dir
1423 # Some paths we'll care about
1424 lambda_path = os.path.join(wc_dir, "A", "B_COPY_1", "lambda")
1425 B_COPY_1_path = os.path.join(wc_dir, "A", "B_COPY_1")
1426 B_COPY_2_path = os.path.join(wc_dir, "A", "B_COPY_2")
1427 E_COPY_2_path = os.path.join(wc_dir, "A", "B_COPY_2", "E")
1428 alpha_path = os.path.join(wc_dir, "A", "B", "E", "alpha")
1429 beta_path = os.path.join(wc_dir, "A", "B", "E", "beta")
1431 # Make branches A/B_COPY_1 and A/B_COPY_2
1432 svntest.actions.run_and_verify_svn(
1433 None,
1434 ["A " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n",
1435 "A " + os.path.join(wc_dir, "A", "B_COPY_1", "E") + "\n",
1436 "A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "alpha") + "\n",
1437 "A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "beta") + "\n",
1438 "A " + os.path.join(wc_dir, "A", "B_COPY_1", "F") + "\n",
1439 "Checked out revision 1.\n",
1440 "A " + B_COPY_1_path + "\n"],
1442 'copy',
1443 sbox.repo_url + "/A/B",
1444 B_COPY_1_path)
1446 svntest.actions.run_and_verify_svn(
1447 None,
1448 ["A " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n",
1449 "A " + os.path.join(wc_dir, "A", "B_COPY_2", "E") + "\n",
1450 "A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "alpha") + "\n",
1451 "A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "beta") + "\n",
1452 "A " + os.path.join(wc_dir, "A", "B_COPY_2", "F") + "\n",
1453 "Checked out revision 1.\n",
1454 "A " + B_COPY_2_path + "\n"],
1456 'copy',
1457 sbox.repo_url + "/A/B",
1458 B_COPY_2_path)
1460 expected_output = svntest.wc.State(wc_dir, {
1461 'A/B_COPY_1' : Item(verb='Adding'),
1462 'A/B_COPY_2' : Item(verb='Adding')
1464 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1465 expected_status.add({
1466 "A/B_COPY_1" : Item(status=' ', wc_rev=2),
1467 "A/B_COPY_1/lambda" : Item(status=' ', wc_rev=2),
1468 "A/B_COPY_1/E" : Item(status=' ', wc_rev=2),
1469 "A/B_COPY_1/E/alpha" : Item(status=' ', wc_rev=2),
1470 "A/B_COPY_1/E/beta" : Item(status=' ', wc_rev=2),
1471 "A/B_COPY_1/F" : Item(status=' ', wc_rev=2),
1472 "A/B_COPY_2" : Item(status=' ', wc_rev=2),
1473 "A/B_COPY_2/lambda" : Item(status=' ', wc_rev=2),
1474 "A/B_COPY_2/E" : Item(status=' ', wc_rev=2),
1475 "A/B_COPY_2/E/alpha" : Item(status=' ', wc_rev=2),
1476 "A/B_COPY_2/E/beta" : Item(status=' ', wc_rev=2),
1477 "A/B_COPY_2/F" : Item(status=' ', wc_rev=2),
1480 svntest.actions.run_and_verify_commit(wc_dir,
1481 expected_output,
1482 expected_status,
1483 None,
1484 wc_dir)
1486 # Make some changes under A/B
1488 # r3 - modify and commit A/B/E/beta
1489 svntest.main.file_write(beta_path, "New content")
1490 expected_output = svntest.wc.State(wc_dir,
1491 {'A/B/E/beta' : Item(verb='Sending')})
1492 expected_status.tweak('A/B/E/beta', wc_rev=3)
1493 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1494 expected_status, None, wc_dir)
1496 # r4 - modify and commit A/B/E/alpha
1497 svntest.main.file_write(alpha_path, "New content")
1498 expected_output = svntest.wc.State(wc_dir,
1499 {'A/B/E/alpha' : Item(verb='Sending')})
1500 expected_status.tweak('A/B/E/alpha', wc_rev=4)
1501 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1502 expected_status, None, wc_dir)
1504 # Merge r2:4 into A/B_COPY_1
1505 short_B_COPY_1_path = shorten_path_kludge(B_COPY_1_path)
1506 expected_output = svntest.wc.State(short_B_COPY_1_path, {
1507 'E/alpha' : Item(status='U '),
1508 'E/beta' : Item(status='U '),
1510 expected_merge_status = svntest.wc.State(short_B_COPY_1_path, {
1511 '' : Item(status=' M', wc_rev=2),
1512 'lambda' : Item(status=' ', wc_rev=2),
1513 'E' : Item(status=' ', wc_rev=2),
1514 'E/alpha' : Item(status='M ', wc_rev=2),
1515 'E/beta' : Item(status='M ', wc_rev=2),
1516 'F' : Item(status=' ', wc_rev=2),
1518 expected_merge_disk = svntest.wc.State('', {
1519 '' : Item(props={SVN_PROP_MERGEINFO : '/A/B:3-4'}),
1520 'lambda' : Item("This is the file 'lambda'.\n"),
1521 'E' : Item(),
1522 'E/alpha' : Item("New content"),
1523 'E/beta' : Item("New content"),
1524 'F' : Item(),
1526 expected_skip = svntest.wc.State(short_B_COPY_1_path, { })
1527 saved_cwd = os.getcwd()
1529 os.chdir(svntest.main.work_dir)
1530 svntest.actions.run_and_verify_merge(short_B_COPY_1_path, '2', '4',
1531 sbox.repo_url + \
1532 '/A/B',
1533 expected_output,
1534 expected_merge_disk,
1535 expected_merge_status,
1536 expected_skip,
1537 None, None, None, None,
1538 None, 1)
1540 os.chdir(saved_cwd)
1542 # r5 - Commit the merge into A/B_COPY_1/E
1543 expected_output = svntest.wc.State(
1544 wc_dir,
1545 {'A/B_COPY_1' : Item(verb='Sending'),
1546 'A/B_COPY_1/E/alpha' : Item(verb='Sending'),
1547 'A/B_COPY_1/E/beta' : Item(verb='Sending'),
1549 expected_status.tweak('A/B_COPY_1', wc_rev=5)
1550 expected_status.tweak('A/B_COPY_1/E/alpha', wc_rev=5)
1551 expected_status.tweak('A/B_COPY_1/E/beta', wc_rev=5)
1552 expected_status.tweak('A/B_COPY_1/lambda', wc_rev=2)
1553 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1554 expected_status, None, wc_dir)
1556 # Merge r2:4 into A/B_COPY_2/E
1557 short_E_COPY_2_path = shorten_path_kludge(E_COPY_2_path)
1558 expected_output = svntest.wc.State(short_E_COPY_2_path, {
1559 'alpha' : Item(status='U '),
1560 'beta' : Item(status='U '),
1562 expected_merge_status = svntest.wc.State(short_E_COPY_2_path, {
1563 '' : Item(status=' M', wc_rev=2),
1564 'alpha' : Item(status='M ', wc_rev=2),
1565 'beta' : Item(status='M ', wc_rev=2),
1567 expected_merge_disk = svntest.wc.State('', {
1568 '' : Item(props={SVN_PROP_MERGEINFO : '/A/B/E:3-4'}),
1569 'alpha' : Item("New content"),
1570 'beta' : Item("New content"),
1572 expected_skip = svntest.wc.State(short_E_COPY_2_path, { })
1573 saved_cwd = os.getcwd()
1575 os.chdir(svntest.main.work_dir)
1576 svntest.actions.run_and_verify_merge(short_E_COPY_2_path, '2', '4',
1577 sbox.repo_url + \
1578 '/A/B/E',
1579 expected_output,
1580 expected_merge_disk,
1581 expected_merge_status,
1582 expected_skip,
1583 None, None, None, None,
1584 None, 1)
1586 os.chdir(saved_cwd)
1588 # Switch A/B_COPY_2 to URL of A/B_COPY_1. The local mergeinfo for r1,3-4
1589 # on A/B_COPY_2/E is identical to the mergeinfo added to A/B_COPY_2 as a
1590 # result of the switch, but we leave the former in place.
1592 # Setup expected results of switch.
1593 expected_output = svntest.wc.State(sbox.wc_dir, {
1594 "A/B_COPY_2" : Item(status=' U'),
1595 "A/B_COPY_2/E/alpha" : Item(status='G '),
1596 "A/B_COPY_2/E/beta" : Item(status='G '),
1599 expected_disk = svntest.main.greek_state.copy()
1600 expected_disk.tweak("A/B/E/alpha", contents="New content")
1601 expected_disk.tweak("A/B/E/beta", contents="New content")
1602 expected_disk.add({
1603 "A/B_COPY_1" : Item(props={SVN_PROP_MERGEINFO : '/A/B:3-4'}),
1604 "A/B_COPY_1/E" : Item(),
1605 "A/B_COPY_1/F" : Item(),
1606 "A/B_COPY_1/lambda" : Item("This is the file 'lambda'.\n"),
1607 "A/B_COPY_1/E/alpha" : Item("New content"),
1608 "A/B_COPY_1/E/beta" : Item("New content"),
1609 "A/B_COPY_2" : Item(props={SVN_PROP_MERGEINFO : '/A/B:3-4'}),
1610 "A/B_COPY_2/E" : Item(props={SVN_PROP_MERGEINFO : '/A/B/E:3-4'}),
1611 "A/B_COPY_2/F" : Item(),
1612 "A/B_COPY_2/lambda" : Item("This is the file 'lambda'.\n"),
1613 "A/B_COPY_2/E/alpha" : Item("New content"),
1614 "A/B_COPY_2/E/beta" : Item("New content"),
1616 expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
1617 expected_status.tweak("A/B/E/beta", wc_rev=3)
1618 expected_status.tweak("A/B/E/alpha", wc_rev=4)
1619 expected_status.add({
1620 "A/B_COPY_1" : Item(status=' ', wc_rev=5),
1621 "A/B_COPY_1/E" : Item(status=' ', wc_rev=2),
1622 "A/B_COPY_1/F" : Item(status=' ', wc_rev=2),
1623 "A/B_COPY_1/lambda" : Item(status=' ', wc_rev=2),
1624 "A/B_COPY_1/E/alpha" : Item(status=' ', wc_rev=5),
1625 "A/B_COPY_1/E/beta" : Item(status=' ', wc_rev=5),
1626 "A/B_COPY_2" : Item(status=' ', wc_rev=5, switched='S'),
1627 "A/B_COPY_2/E" : Item(status=' M', wc_rev=5),
1628 "A/B_COPY_2/F" : Item(status=' ', wc_rev=5),
1629 "A/B_COPY_2/lambda" : Item(status=' ', wc_rev=5),
1630 "A/B_COPY_2/E/alpha" : Item(status=' ', wc_rev=5),
1631 "A/B_COPY_2/E/beta" : Item(status=' ', wc_rev=5),
1634 svntest.actions.run_and_verify_switch(sbox.wc_dir,
1635 B_COPY_2_path,
1636 sbox.repo_url + "/A/B_COPY_1",
1637 expected_output,
1638 expected_disk,
1639 expected_status,
1640 None, None, None, None, None, 1)
1642 # Now check a switch which reverses and earlier switch and leaves
1643 # a path in an unswitched state.
1645 # Switch A/B_COPY_1/lambda to iota. Use propset to give A/B_COPY/lambda
1646 # the mergeinfo '/A/B/lambda:1,3-4'. Then switch A/B_COPY_1/lambda back
1647 # to A/B_COPY_1/lambda. The local mergeinfo for r1,3-4 should remain on
1648 # A/B_COPY_1/lambda.
1649 expected_output = svntest.wc.State(sbox.wc_dir, {
1650 "A/B_COPY_1/lambda" : Item(status='U '),
1652 expected_disk.tweak("A/B_COPY_1/lambda",
1653 contents="This is the file 'iota'.\n")
1654 expected_status.tweak("A/B_COPY_1/lambda", wc_rev=5, switched='S')
1655 svntest.actions.run_and_verify_switch(sbox.wc_dir,
1656 lambda_path,
1657 sbox.repo_url + "/iota",
1658 expected_output,
1659 expected_disk,
1660 expected_status,
1661 None, None, None, None, None, 1)
1663 svntest.actions.run_and_verify_svn(None,
1664 ["property '" + SVN_PROP_MERGEINFO +
1665 "' set on '" + lambda_path + "'" +
1666 "\n"], [], 'ps', SVN_PROP_MERGEINFO,
1667 '/A/B/lambda:3-4', lambda_path)
1669 expected_output = svntest.wc.State(sbox.wc_dir, {
1670 "A/B_COPY_1/lambda" : Item(status='U '),
1672 expected_disk.tweak("A/B_COPY_1/lambda",
1673 contents="This is the file 'lambda'.\n",
1674 props={SVN_PROP_MERGEINFO : '/A/B/lambda:3-4'})
1675 expected_status.tweak("A/B_COPY_1/lambda", switched=None, status=' M')
1676 svntest.actions.run_and_verify_switch(sbox.wc_dir,
1677 lambda_path,
1678 sbox.repo_url + "/A/B_COPY_1/lambda",
1679 expected_output,
1680 expected_disk,
1681 expected_status,
1682 None, None, None, None, None, 1)
1684 #----------------------------------------------------------------------
1686 def switch_with_depth(sbox):
1687 "basic tests to verify switch along with depth"
1689 sbox.build(read_only = True)
1691 # Form some paths and URLs required
1692 wc_dir = sbox.wc_dir
1693 repo_url = sbox.repo_url
1694 AD_url = repo_url + '/A/D'
1695 AB_url = repo_url + '/A/B'
1696 AB_path = os.path.join(wc_dir, 'A', 'B')
1698 # Set up expected results of 'switch --depth=empty'
1699 expected_output = svntest.wc.State(wc_dir, {})
1700 expected_disk = svntest.main.greek_state.copy()
1701 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1702 expected_status.tweak('A/B', switched='S')
1703 expected_status.tweak('A/B/lambda', switched='S')
1704 expected_status.tweak('A/B/E', switched='S')
1705 expected_status.tweak('A/B/F', switched='S')
1707 # Do 'switch --depth=empty' and check the results in three ways.
1708 svntest.actions.run_and_verify_switch(wc_dir, AB_path, AD_url,
1709 expected_output,
1710 expected_disk,
1711 expected_status, None,
1712 None, None, None, None, 0,
1713 '--depth', 'empty')
1715 # Set up expected results for reverting 'switch --depth=empty'
1716 expected_output = svntest.wc.State(wc_dir, {})
1717 expected_disk = svntest.main.greek_state.copy()
1718 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1720 svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url,
1721 expected_output,
1722 expected_disk,
1723 expected_status, None,
1724 None, None, None, None, 0,
1725 '--depth', 'empty')
1727 # Set up expected results of 'switch --depth=files'
1728 expected_output = svntest.wc.State(wc_dir, {
1729 'A/B/lambda' : Item(status='D '),
1730 'A/B/gamma' : Item(status='A '),
1732 expected_disk = svntest.main.greek_state.copy()
1733 expected_disk.remove('A/B/lambda')
1734 expected_disk.add({
1735 'A/B/gamma' : Item("This is the file 'gamma'.\n")
1737 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1738 expected_status.remove('A/B/lambda')
1739 expected_status.add({
1740 'A/B/gamma' : Item(status=' ', wc_rev=1)
1742 expected_status.tweak('A/B', switched='S')
1743 expected_status.tweak('A/B/E', switched='S')
1744 expected_status.tweak('A/B/F', switched='S')
1746 # Do 'switch --depth=files' and check the results in three ways.
1747 svntest.actions.run_and_verify_switch(wc_dir, AB_path, AD_url,
1748 expected_output,
1749 expected_disk,
1750 expected_status, None,
1751 None, None, None, None, 0,
1752 '--depth', 'files')
1754 # Set up expected results for reverting 'switch --depth=files'
1755 expected_output = svntest.wc.State(wc_dir, {
1756 'A/B/gamma' : Item(status='D '),
1757 'A/B/lambda' : Item(status='A '),
1759 expected_disk = svntest.main.greek_state.copy()
1760 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1762 svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url,
1763 expected_output,
1764 expected_disk,
1765 expected_status, None,
1766 None, None, None, None, 0,
1767 '--depth', 'files')
1769 # Putting the depth=immediates stuff in a subroutine, because we're
1770 # going to run it at least twice.
1771 def sw_depth_imm():
1772 # Set up expected results of 'switch --depth=immediates'
1773 expected_output = svntest.wc.State(wc_dir, {
1774 'A/B/lambda' : Item(status='D '),
1775 'A/B/E' : Item(status='D '),
1776 'A/B/F' : Item(status='D '),
1777 'A/B/gamma' : Item(status='A '),
1778 'A/B/G' : Item(status='A '),
1779 'A/B/H' : Item(status='A '),
1781 expected_disk = svntest.main.greek_state.copy()
1782 expected_disk.remove('A/B/lambda', 'A/B/E/beta', 'A/B/E/alpha',
1783 'A/B/E', 'A/B/F')
1784 expected_disk.add({
1785 'A/B/gamma' : Item("This is the file 'gamma'.\n"),
1786 'A/B/G' : Item(),
1787 'A/B/H' : Item(),
1789 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1790 expected_status.remove('A/B/lambda', 'A/B/E/beta', 'A/B/E/alpha',
1791 'A/B/E', 'A/B/F')
1792 expected_status.add({
1793 'A/B/gamma' : Item(status=' ', wc_rev=1),
1794 'A/B/G' : Item(status=' ', wc_rev=1),
1795 'A/B/H' : Item(status=' ', wc_rev=1)
1797 expected_status.tweak('A/B', switched='S')
1799 # Do 'switch --depth=immediates' and check the results in three ways.
1800 svntest.actions.run_and_verify_switch(wc_dir, AB_path, AD_url,
1801 expected_output,
1802 expected_disk,
1803 expected_status, None,
1804 None, None, None, None, 0,
1805 '--depth', 'immediates')
1807 sw_depth_imm()
1809 # Set up expected results for reverting 'switch --depth=immediates'.
1810 # (Reverting with default [infinite] depth, so that the result is a
1811 # standard Greek Tree working copy again.)
1812 expected_output = svntest.wc.State(wc_dir, {
1813 'A/B/gamma' : Item(status='D '),
1814 'A/B/G' : Item(status='D '),
1815 'A/B/H' : Item(status='D '),
1816 'A/B/lambda' : Item(status='A '),
1817 'A/B/E' : Item(status='A '),
1818 'A/B/E/alpha' : Item(status='A '),
1819 'A/B/E/beta' : Item(status='A '),
1820 'A/B/F' : Item(status='A '),
1822 expected_disk = svntest.main.greek_state.copy()
1823 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1824 svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url,
1825 expected_output,
1826 expected_disk,
1827 expected_status, None,
1828 None, None, None, None, 0)
1830 # Okay, repeat 'switch --depth=immediates'. (Afterwards we'll
1831 # 'switch --depth=infinity', to test going all the way.)
1832 sw_depth_imm()
1834 # Set up expected results of 'switch --depth=infinity'
1835 expected_output = svntest.wc.State(wc_dir, {
1836 'A/B/gamma' : Item(status='D '),
1837 'A/B/G' : Item(status='D '),
1838 'A/B/H' : Item(status='D '),
1839 'A/B/lambda' : Item(status='A '),
1840 'A/B/E' : Item(status='A '),
1841 'A/B/E/alpha' : Item(status='A '),
1842 'A/B/E/beta' : Item(status='A '),
1843 'A/B/F' : Item(status='A '),
1845 expected_disk = svntest.main.greek_state.copy()
1846 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1848 # Do the 'switch --depth=infinity' and check the results in three ways.
1849 svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url,
1850 expected_output,
1851 expected_disk,
1852 expected_status, None,
1853 None, None, None, None, 0,
1854 '--depth', 'infinity')
1856 #----------------------------------------------------------------------
1858 def switch_to_dir_with_peg_rev(sbox):
1859 "switch to dir@peg where dir doesn't exist in HEAD"
1861 sbox.build()
1862 wc_dir = sbox.wc_dir
1863 repo_url = sbox.repo_url
1865 # prepare two dirs X and Y in rev. 2
1866 X_path = os.path.join(wc_dir, 'X')
1867 Y_path = os.path.join(wc_dir, 'Y')
1868 svntest.main.run_svn(None, 'mkdir', X_path, Y_path)
1869 svntest.main.run_svn(None, 'ci',
1870 '-m', 'log message',
1871 wc_dir)
1873 # change tau in rev. 3
1874 ADG_path = os.path.join(wc_dir, 'A', 'D', 'G')
1875 tau_path = os.path.join(ADG_path, 'tau')
1876 svntest.main.file_append(tau_path, "new line\n")
1877 svntest.main.run_svn(None, 'ci',
1878 '-m', 'log message',
1879 wc_dir)
1881 # delete A/D/G in rev. 4
1882 svntest.main.run_svn(None, 'up', wc_dir)
1883 svntest.main.run_svn(None, 'rm', ADG_path)
1884 svntest.main.run_svn(None, 'ci',
1885 '-m', 'log message',
1886 wc_dir)
1888 # Test 1: switch X to A/D/G@2
1889 ADG_url = repo_url + '/A/D/G'
1890 expected_output = svntest.wc.State(wc_dir, {
1891 'X/pi' : Item(status='A '),
1892 'X/rho' : Item(status='A '),
1893 'X/tau' : Item(status='A '),
1895 expected_disk = svntest.main.greek_state.copy()
1896 expected_disk.add({
1897 'X' : Item(),
1898 'X/pi' : Item("This is the file 'pi'.\n"),
1899 'X/rho' : Item("This is the file 'rho'.\n"),
1900 'X/tau' : Item("This is the file 'tau'.\n"),
1901 'Y' : Item(),
1903 expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1904 expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
1905 expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1906 expected_status.add({
1907 'X' : Item(status=' ', wc_rev=2, switched='S'),
1908 'X/pi' : Item(status=' ', wc_rev=2),
1909 'X/rho' : Item(status=' ', wc_rev=2),
1910 'X/tau' : Item(status=' ', wc_rev=2),
1911 'Y' : Item(status=' ', wc_rev=3)
1914 # Do the switch to rev. 2 of /A/D/G@3.
1915 svntest.actions.run_and_verify_switch(wc_dir, X_path, ADG_url + '@3',
1916 expected_output,
1917 expected_disk,
1918 expected_status, None,
1919 None, None, None, None, 0,
1920 '-r', '2')
1922 def switch_urls_with_spaces(sbox):
1923 "switch file and dir to url containing spaces"
1925 sbox.build()
1926 wc_dir = sbox.wc_dir
1927 repo_url = sbox.repo_url
1929 # add file and directory with spaces in their names.
1930 XYZ_path = os.path.join(wc_dir, 'X Y Z')
1931 ABC_path = os.path.join(wc_dir, 'A B C')
1932 svntest.main.run_svn(None, 'mkdir', XYZ_path, ABC_path)
1934 tpm_path = os.path.join(wc_dir, 'tau pau mau')
1935 bbb_path = os.path.join(wc_dir, 'bar baz bal')
1936 svntest.main.file_write(tpm_path, "This is the file 'tau pau mau'.\n")
1937 svntest.main.file_write(bbb_path, "This is the file 'bar baz bal'.\n")
1938 svntest.main.run_svn(None, 'add', tpm_path, bbb_path)
1940 svntest.main.run_svn(None, 'ci', '-m', 'log message', wc_dir)
1942 # Test 1: switch directory 'A B C' to url 'X Y Z'
1943 XYZ_url = repo_url + '/X Y Z'
1944 expected_output = svntest.wc.State(wc_dir, {
1946 expected_disk = svntest.main.greek_state.copy()
1947 expected_disk.add({
1948 'X Y Z' : Item(),
1949 'A B C' : Item(),
1950 'tau pau mau' : Item("This is the file 'tau pau mau'.\n"),
1951 'bar baz bal' : Item("This is the file 'bar baz bal'.\n"),
1953 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1954 expected_status.add({
1955 'X Y Z' : Item(status=' ', wc_rev=2),
1956 'A B C' : Item(status=' ', wc_rev=2, switched='S'),
1957 'tau pau mau' : Item(status=' ', wc_rev=2),
1958 'bar baz bal' : Item(status=' ', wc_rev=2),
1961 svntest.actions.run_and_verify_switch(wc_dir, ABC_path, XYZ_url,
1962 expected_output,
1963 expected_disk,
1964 expected_status)
1966 # Test 2: switch file 'bar baz bal' to 'tau pau mau'
1967 tpm_url = repo_url + '/tau pau mau'
1968 expected_output = svntest.wc.State(wc_dir, {
1969 'bar baz bal' : Item(status='U '),
1971 expected_disk = svntest.main.greek_state.copy()
1972 expected_disk.add({
1973 'X Y Z' : Item(),
1974 'A B C' : Item(),
1975 'tau pau mau' : Item("This is the file 'tau pau mau'.\n"),
1976 'bar baz bal' : Item("This is the file 'tau pau mau'.\n"),
1978 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1979 expected_status.add({
1980 'X Y Z' : Item(status=' ', wc_rev=2),
1981 'A B C' : Item(status=' ', wc_rev=2, switched='S'),
1982 'tau pau mau' : Item(status=' ', wc_rev=2),
1983 'bar baz bal' : Item(status=' ', wc_rev=2, switched='S'),
1986 svntest.actions.run_and_verify_switch(wc_dir, bbb_path, tpm_url,
1987 expected_output,
1988 expected_disk,
1989 expected_status)
1991 def switch_to_dir_with_peg_rev2(sbox):
1992 "switch to old rev of now renamed branch"
1994 sbox.build()
1995 wc_dir = sbox.wc_dir
1996 repo_url = sbox.repo_url
1998 # prepare dir X in rev. 2
1999 X_path = os.path.join(wc_dir, 'X')
2000 svntest.main.run_svn(None, 'mkdir', X_path)
2001 svntest.main.run_svn(None, 'ci',
2002 '-m', 'log message',
2003 wc_dir)
2005 # make a change in ADG in rev. 3
2006 tau_path = os.path.join(wc_dir, 'A', 'D', 'G', 'tau')
2007 svntest.main.file_append(tau_path, "extra line\n")
2008 svntest.main.run_svn(None, 'ci', '-m', 'log message', wc_dir)
2010 # Rename ADG to ADY in rev 4
2011 svntest.main.run_svn(None, 'up', wc_dir)
2012 ADG_path = os.path.join(wc_dir, 'A', 'D', 'G')
2013 ADY_path = os.path.join(wc_dir, 'A', 'D', 'Y')
2014 svntest.main.run_svn(None, 'mv', ADG_path, ADY_path)
2015 svntest.main.run_svn(None, 'ci',
2016 '-m', 'log message',
2017 wc_dir)
2019 # Test switch X to rev 2 of A/D/Y@HEAD
2020 ADY_url = sbox.repo_url + '/A/D/Y'
2021 expected_output = svntest.wc.State(wc_dir, {
2022 'X/pi' : Item(status='A '),
2023 'X/rho' : Item(status='A '),
2024 'X/tau' : Item(status='A '),
2026 expected_disk = svntest.main.greek_state.copy()
2027 expected_disk.add({
2028 'X' : Item(),
2029 'X/pi' : Item("This is the file 'pi'.\n"),
2030 'X/rho' : Item("This is the file 'rho'.\n"),
2031 'X/tau' : Item("This is the file 'tau'.\n"),
2032 'A/D/Y' : Item(),
2033 'A/D/Y/pi' : Item("This is the file 'pi'.\n"),
2034 'A/D/Y/rho' : Item("This is the file 'rho'.\n"),
2035 'A/D/Y/tau' : Item("This is the file 'tau'.\nextra line\n"),
2037 expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2039 expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
2040 expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2041 expected_status.add({
2042 'X' : Item(status=' ', wc_rev=2, switched='S'),
2043 'X/pi' : Item(status=' ', wc_rev=2),
2044 'X/rho' : Item(status=' ', wc_rev=2),
2045 'X/tau' : Item(status=' ', wc_rev=2),
2046 'A/D/Y' : Item(status=' ', wc_rev=4),
2047 'A/D/Y/pi' : Item(status=' ', wc_rev=4),
2048 'A/D/Y/rho' : Item(status=' ', wc_rev=4),
2049 'A/D/Y/tau' : Item(status=' ', wc_rev=4),
2052 svntest.actions.run_and_verify_switch(wc_dir, X_path, ADY_url + '@HEAD',
2053 expected_output,
2054 expected_disk,
2055 expected_status, None,
2056 None, None, None, None, 0,
2057 '-r', '2')
2059 def switch_to_root(sbox):
2060 "switch a folder to the root of its repository"
2062 sbox.build(read_only = True)
2063 wc_dir = sbox.wc_dir
2064 repo_url = sbox.repo_url
2066 ADG_path = os.path.join(wc_dir, 'A', 'D', 'G')
2068 # Test switch /A/D/G to /
2069 AD_url = sbox.repo_url + '/A/D'
2070 expected_output = svntest.wc.State(wc_dir, {
2071 'A/D/G/pi' : Item(status='D '),
2072 'A/D/G/rho' : Item(status='D '),
2073 'A/D/G/tau' : Item(status='D '),
2074 'A/D/G/A' : Item(status='A '),
2075 'A/D/G/A/B' : Item(status='A '),
2076 'A/D/G/A/B/lambda' : Item(status='A '),
2077 'A/D/G/A/B/E' : Item(status='A '),
2078 'A/D/G/A/B/E/alpha' : Item(status='A '),
2079 'A/D/G/A/B/E/beta' : Item(status='A '),
2080 'A/D/G/A/B/F' : Item(status='A '),
2081 'A/D/G/A/mu' : Item(status='A '),
2082 'A/D/G/A/C' : Item(status='A '),
2083 'A/D/G/A/D' : Item(status='A '),
2084 'A/D/G/A/D/gamma' : Item(status='A '),
2085 'A/D/G/A/D/G' : Item(status='A '),
2086 'A/D/G/A/D/G/pi' : Item(status='A '),
2087 'A/D/G/A/D/G/rho' : Item(status='A '),
2088 'A/D/G/A/D/G/tau' : Item(status='A '),
2089 'A/D/G/A/D/H' : Item(status='A '),
2090 'A/D/G/A/D/H/chi' : Item(status='A '),
2091 'A/D/G/A/D/H/omega' : Item(status='A '),
2092 'A/D/G/A/D/H/psi' : Item(status='A '),
2093 'A/D/G/iota' : Item(status='A '),
2095 expected_disk = svntest.main.greek_state.copy()
2096 expected_disk.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2097 expected_disk.add_state('A/D/G', svntest.main.greek_state.copy())
2099 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2100 expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2101 expected_status.add_state('A/D/G',
2102 svntest.actions.get_virginal_state(wc_dir, 1))
2103 expected_status.tweak('A/D/G', switched = 'S')
2104 svntest.actions.run_and_verify_switch(wc_dir, ADG_path, sbox.repo_url,
2105 expected_output,
2106 expected_disk,
2107 expected_status)
2109 ########################################################################
2110 # Run the tests
2112 # list all tests here, starting with None:
2113 test_list = [ None,
2114 routine_switching,
2115 commit_switched_things,
2116 full_update,
2117 full_rev_update,
2118 update_switched_things,
2119 rev_update_switched_things,
2120 log_switched_file,
2121 relocate_deleted_missing_copied,
2122 delete_subdir,
2123 XFail(file_dir_file),
2124 nonrecursive_switching,
2125 failed_anchor_is_target,
2126 bad_intermediate_urls,
2127 obstructed_switch,
2128 commit_mods_below_switch,
2129 relocate_beyond_repos_root,
2130 refresh_read_only_attribute,
2131 switch_change_repos_root,
2132 XFail(relocate_and_propset, svntest.main.is_ra_type_dav),
2133 forced_switch,
2134 forced_switch_failures,
2135 switch_scheduled_add,
2136 mergeinfo_switch_elision,
2137 switch_with_obstructing_local_adds,
2138 switch_with_depth,
2139 switch_to_dir_with_peg_rev,
2140 switch_urls_with_spaces,
2141 switch_to_dir_with_peg_rev2,
2142 switch_to_root,
2145 if __name__ == '__main__':
2146 svntest.main.run_tests(test_list)
2147 # NOTREACHED
2150 ### End of file.