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 ######################################################################
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.
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')
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),
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')
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"),
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'
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
,
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'
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
,
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")
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(
183 "svn: Cannot commit both .* as they refer to the same URL$",
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
210 svntest
.actions
.run_and_verify_commit(wc_dir
,
215 svntest
.main
.run_svn(None,
216 'ci', '-m', 'log msg', wc_dir
)
219 ######################################################################
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"
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"
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")
297 'A/B/Z/zeta' : Item(contents
="This is the file 'zeta'.\n"),
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
,
318 #----------------------------------------------------------------------
320 def full_rev_update(sbox
):
321 "reverse update wc that contains switched things"
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
,
368 #----------------------------------------------------------------------
370 def update_switched_things(sbox
):
371 "update switched wc things to HEAD"
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")
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',
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
,
428 #----------------------------------------------------------------------
430 def rev_update_switched_things(sbox
):
431 "reverse update switched wc things to an older rev"
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")
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',
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
,
487 #----------------------------------------------------------------------
489 def log_switched_file(sbox
):
490 "show logs for a switched file"
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,
503 'set prop on switched iota',
506 # log switched file 'iota'
507 output
, error
= svntest
.main
.run_svn(None, 'log', iota_path
)
509 if line
.find("set prop on switched iota") != -1:
512 raise svntest
.Failure
514 #----------------------------------------------------------------------
516 def relocate_deleted_missing_copied(sbox
):
517 "relocate with deleted, missing and copied entries"
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
,
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',
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
)
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')
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',
579 svntest
.actions
.run_and_verify_update(wc_dir
,
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
,
595 #----------------------------------------------------------------------
597 def delete_subdir(sbox
):
598 "switch that deletes a sub-directory"
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
,
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)
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"
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,
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, [],
695 if out
[1].find('/A/B') == -1:
697 raise svntest
.Failure
699 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
701 if out
[1].find('/A/C') == -1:
703 raise svntest
.Failure
705 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
707 if out
[1].find('/A/D') == -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.)
715 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
717 if out
[2].find('/branch/version1/mu') == -1:
719 raise svntest
.Failure
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:
725 raise svntest
.Failure
728 #----------------------------------------------------------------------
729 def failed_anchor_is_target(sbox
):
730 "anchor=target that fails due to local mods"
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',
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
)
772 if line
.find('URL: ' + G_url
) != -1:
775 raise svntest
.Failure
777 # Remove the now-unversioned psi, and repeat the switch. This
778 # should complete the switch.
780 svntest
.actions
.run_and_verify_svn(None, None, [], 'switch',
783 expected_status
.tweak('A/D/H', status
=' ') # remains switched
784 expected_status
.add({ 'A/D/H/psi' : Item(status
=' ',
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"
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',
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',
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, [],
823 if out
[1].find('/A/C/A') == -1:
824 raise svntest
.Failure
828 #----------------------------------------------------------------------
829 # Regression test for issue #1825: failed switch may corrupt
832 def obstructed_switch(sbox
):
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
,
855 svntest
.main
.file_append(alpha_path
, "hello")
856 out
, err
= svntest
.main
.run_svn(1,
857 'sw', E_url2
, E_path
)
859 if line
.find("object of the same name already exists") != -1:
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 #----------------------------------------------------------------------
874 def commit_mods_below_switch(sbox
):
875 "commit with mods below switch"
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()
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"),
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
,
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)
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
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
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 #----------------------------------------------------------------------
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:
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',
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
,
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
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
,
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"
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,
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.*",
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
)
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
)
1094 svntest
.main
.safe_rmtree(wc_dir
, 1)
1095 svntest
.actions
.run_and_verify_svn(None,
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
,
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
,
1140 #----------------------------------------------------------------------
1142 def forced_switch(sbox
):
1143 "forced switch tolerates obstructions to adds"
1144 sbox
.build(read_only
= True)
1147 G_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'G')
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')
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()
1182 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
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"),
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"),
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
,
1214 expected_status
, None,
1215 None, None, None, None, 0,
1218 #----------------------------------------------------------------------
1220 def forced_switch_failures(sbox
):
1221 "forced switch fails with some types of obstuctions"
1224 # Add a directory to obstruct a file.
1225 pi_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'pi')
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",
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
,
1250 sbox
.repo_url
+ "/A/D/G",
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'],
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')
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
,
1282 sbox
.repo_url
+ "/A/D/H",
1284 ".*Failed to add " + \
1285 "directory .*: a versioned " + \
1286 "directory of the same name " + \
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')
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'),
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')
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
,
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()
1339 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
1341 "A/B/F/G/pi" : Item("\n".join(["<<<<<<< .mine",
1342 "This is the OBSTRUCTING file 'pi'.",
1344 "This is the file 'pi'.",
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"),
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"),
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
,
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, [],
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
1416 def shorten_path_kludge(path
):
1417 shorten_by
= len(svntest
.main
.work_dir
) + len(os
.sep
)
1418 return path
[shorten_by
:]
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(
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"],
1443 sbox
.repo_url
+ "/A/B",
1446 svntest
.actions
.run_and_verify_svn(
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"],
1457 sbox
.repo_url
+ "/A/B",
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
,
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"),
1522 'E/alpha' : Item("New content"),
1523 'E/beta' : Item("New content"),
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',
1534 expected_merge_disk
,
1535 expected_merge_status
,
1537 None, None, None, None,
1542 # r5 - Commit the merge into A/B_COPY_1/E
1543 expected_output
= svntest
.wc
.State(
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',
1580 expected_merge_disk
,
1581 expected_merge_status
,
1583 None, None, None, None,
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")
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
,
1636 sbox
.repo_url
+ "/A/B_COPY_1",
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
,
1657 sbox
.repo_url
+ "/iota",
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
,
1678 sbox
.repo_url
+ "/A/B_COPY_1/lambda",
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
,
1711 expected_status
, None,
1712 None, None, None, None, 0,
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
,
1723 expected_status
, None,
1724 None, None, None, None, 0,
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')
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
,
1750 expected_status
, None,
1751 None, None, None, None, 0,
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
,
1765 expected_status
, None,
1766 None, None, None, None, 0,
1769 # Putting the depth=immediates stuff in a subroutine, because we're
1770 # going to run it at least twice.
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',
1785 'A/B/gamma' : Item("This is the file 'gamma'.\n"),
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',
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
,
1803 expected_status
, None,
1804 None, None, None, None, 0,
1805 '--depth', 'immediates')
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
,
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.)
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
,
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"
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',
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',
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',
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()
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"),
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',
1918 expected_status
, None,
1919 None, None, None, None, 0,
1922 def switch_urls_with_spaces(sbox
):
1923 "switch file and dir to url containing spaces"
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()
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
,
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()
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
,
1991 def switch_to_dir_with_peg_rev2(sbox
):
1992 "switch to old rev of now renamed branch"
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',
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',
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()
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"),
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',
2055 expected_status
, None,
2056 None, None, None, None, 0,
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
,
2109 ########################################################################
2112 # list all tests here, starting with None:
2115 commit_switched_things
,
2118 update_switched_things
,
2119 rev_update_switched_things
,
2121 relocate_deleted_missing_copied
,
2123 XFail(file_dir_file
),
2124 nonrecursive_switching
,
2125 failed_anchor_is_target
,
2126 bad_intermediate_urls
,
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
),
2134 forced_switch_failures
,
2135 switch_scheduled_add
,
2136 mergeinfo_switch_elision
,
2137 switch_with_obstructing_local_adds
,
2139 switch_to_dir_with_peg_rev
,
2140 switch_urls_with_spaces
,
2141 switch_to_dir_with_peg_rev2
,
2145 if __name__
== '__main__':
2146 svntest
.main
.run_tests(test_list
)