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_MERGE_INFO
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$",
184 None, None, None, None,
187 # Okay, that all taken care of, let's revert the A/D/G/pi path and
188 # move along. Afterward, we should be okay to commit. (Sorry,
189 # holsta, that banana has to go...)
190 svntest
.main
.run_svn(None, 'revert', Gpi_path
)
192 # Create expected output tree.
193 expected_output
= svntest
.wc
.State(wc_dir
, {
194 'A/D/G/Z' : Item(verb
='Adding'),
195 'A/D/G/Z/zeta' : Item(verb
='Adding'),
196 'iota' : Item(verb
='Sending'),
197 'A/B/pi' : Item(verb
='Sending'),
200 # Created expected status tree.
201 expected_status
= get_routine_status_state(wc_dir
)
202 expected_status
.tweak('iota', 'A/B', switched
='S')
203 expected_status
.tweak('iota', 'A/B/pi', wc_rev
=2, status
=' ')
204 expected_status
.add({
205 'A/D/G/Z' : Item(status
=' ', wc_rev
=2),
206 'A/D/G/Z/zeta' : Item(status
=' ', wc_rev
=2),
209 # Commit should succeed
211 svntest
.actions
.run_and_verify_commit(wc_dir
,
214 None, None, None, None, None,
217 svntest
.main
.run_svn(None,
218 'ci', '-m', 'log msg', wc_dir
)
221 ######################################################################
225 #----------------------------------------------------------------------
227 def routine_switching(sbox
):
228 "test some basic switching operations"
232 # Setup (and verify) some switched things
233 do_routine_switching(sbox
.wc_dir
, sbox
.repo_url
, 1)
236 #----------------------------------------------------------------------
238 def commit_switched_things(sbox
):
239 "commits after some basic switching operations"
244 # Setup some switched things (don't bother verifying)
245 do_routine_switching(wc_dir
, sbox
.repo_url
, 0)
247 # Commit some stuff (and verify)
248 commit_routine_switching(wc_dir
, 1)
251 #----------------------------------------------------------------------
253 def full_update(sbox
):
254 "update wc that contains switched things"
259 # Setup some switched things (don't bother verifying)
260 do_routine_switching(wc_dir
, sbox
.repo_url
, 0)
262 # Copy wc_dir to a backup location
263 wc_backup
= sbox
.add_wc_path('backup')
264 svntest
.actions
.duplicate_dir(wc_dir
, wc_backup
)
266 # Commit some stuff (don't bother verifying)
267 commit_routine_switching(wc_backup
, 0)
269 # Some convenient path variables
270 iota_path
= os
.path
.join(wc_dir
, 'iota')
271 gamma_path
= os
.path
.join(wc_dir
, 'A', 'D', 'gamma')
272 Bpi_path
= os
.path
.join(wc_dir
, 'A', 'B', 'pi')
273 BZ_path
= os
.path
.join(wc_dir
, 'A', 'B', 'Z')
274 Bzeta_path
= os
.path
.join(wc_dir
, 'A', 'B', 'Z', 'zeta')
275 Gpi_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'pi')
276 GZ_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'Z')
277 Gzeta_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'Z', 'zeta')
279 # Create expected output tree for an update of wc_backup.
280 expected_output
= svntest
.wc
.State(wc_dir
, {
281 'iota' : Item(status
='U '),
282 'A/D/gamma' : Item(status
='U '),
283 'A/B/pi' : Item(status
='U '),
284 'A/B/Z' : Item(status
='A '),
285 'A/B/Z/zeta' : Item(status
='A '),
286 'A/D/G/pi' : Item(status
='U '),
287 'A/D/G/Z' : Item(status
='A '),
288 'A/D/G/Z/zeta' : Item(status
='A '),
291 # Create expected disk tree for the update
292 expected_disk
= get_routine_disk_state(wc_dir
)
293 expected_disk
.tweak('iota', contents
="This is the file 'gamma'.\napple")
294 expected_disk
.tweak('A/D/gamma', contents
="This is the file 'gamma'.\napple")
295 expected_disk
.tweak('A/B/pi', contents
="This is the file 'pi'.\nmelon")
296 expected_disk
.tweak('A/D/G/pi', contents
="This is the file 'pi'.\nmelon")
299 'A/B/Z/zeta' : Item(contents
="This is the file 'zeta'.\n"),
301 'A/D/G/Z/zeta' : Item(contents
="This is the file 'zeta'.\n"),
304 # Create expected status tree for the update.
305 expected_status
= get_routine_status_state(wc_dir
)
306 expected_status
.tweak(wc_rev
=2)
307 expected_status
.add({
308 'A/D/G/Z' : Item(status
=' ', wc_rev
=2),
309 'A/D/G/Z/zeta' : Item(status
=' ', wc_rev
=2),
310 'A/B/Z' : Item(status
=' ', wc_rev
=2),
311 'A/B/Z/zeta' : Item(status
=' ', wc_rev
=2),
313 expected_status
.tweak('iota', 'A/B', switched
='S')
315 svntest
.actions
.run_and_verify_update(wc_dir
,
320 #----------------------------------------------------------------------
322 def full_rev_update(sbox
):
323 "reverse update wc that contains switched things"
328 # Setup some switched things (don't bother verifying)
329 do_routine_switching(wc_dir
, sbox
.repo_url
, 0)
331 # Commit some stuff (don't bother verifying)
332 commit_routine_switching(wc_dir
, 0)
334 # Update to HEAD (tested elsewhere)
335 svntest
.main
.run_svn(None, 'up', wc_dir
)
337 # Some convenient path variables
338 iota_path
= os
.path
.join(wc_dir
, 'iota')
339 gamma_path
= os
.path
.join(wc_dir
, 'A', 'D', 'gamma')
340 Bpi_path
= os
.path
.join(wc_dir
, 'A', 'B', 'pi')
341 BZ_path
= os
.path
.join(wc_dir
, 'A', 'B', 'Z')
342 Gpi_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'pi')
343 GZ_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'Z')
345 # Now, reverse update, back to the pre-commit state.
346 expected_output
= svntest
.wc
.State(wc_dir
, {
347 'iota' : Item(status
='U '),
348 'A/D/gamma' : Item(status
='U '),
349 'A/B/pi' : Item(status
='U '),
350 'A/B/Z' : Item(status
='D '),
351 'A/D/G/pi' : Item(status
='U '),
352 'A/D/G/Z' : Item(status
='D '),
355 # Create expected disk tree
356 expected_disk
= get_routine_disk_state(wc_dir
)
358 # Create expected status
359 expected_status
= get_routine_status_state(wc_dir
)
360 expected_status
.tweak('iota', 'A/B', switched
='S')
362 svntest
.actions
.run_and_verify_update(wc_dir
,
370 #----------------------------------------------------------------------
372 def update_switched_things(sbox
):
373 "update switched wc things to HEAD"
378 # Setup some switched things (don't bother verifying)
379 do_routine_switching(wc_dir
, sbox
.repo_url
, 0)
381 # Copy wc_dir to a backup location
382 wc_backup
= sbox
.add_wc_path('backup')
383 svntest
.actions
.duplicate_dir(wc_dir
, wc_backup
)
385 # Commit some stuff (don't bother verifying)
386 commit_routine_switching(wc_backup
, 0)
388 # Some convenient path variables
389 iota_path
= os
.path
.join(wc_dir
, 'iota')
390 B_path
= os
.path
.join(wc_dir
, 'A', 'B')
392 # Create expected output tree for an update of wc_backup.
393 expected_output
= svntest
.wc
.State(wc_dir
, {
394 'iota' : Item(status
='U '),
395 'A/B/pi' : Item(status
='U '),
396 'A/B/Z' : Item(status
='A '),
397 'A/B/Z/zeta' : Item(status
='A '),
400 # Create expected disk tree for the update
401 expected_disk
= get_routine_disk_state(wc_dir
)
402 expected_disk
.tweak('iota', contents
="This is the file 'gamma'.\napple")
404 expected_disk
.tweak('A/B/pi', contents
="This is the file 'pi'.\nmelon")
407 'A/B/Z/zeta' : Item("This is the file 'zeta'.\n"),
410 # Create expected status tree for the update.
411 expected_status
= get_routine_status_state(wc_dir
)
412 expected_status
.tweak('iota', 'A/B', switched
='S')
413 expected_status
.tweak('A/B', 'A/B/pi', 'A/B/rho', 'A/B/tau', 'iota',
415 expected_status
.add({
416 'A/B/Z' : Item(status
=' ', wc_rev
=2),
417 'A/B/Z/zeta' : Item(status
=' ', wc_rev
=2),
420 svntest
.actions
.run_and_verify_update(wc_dir
,
430 #----------------------------------------------------------------------
432 def rev_update_switched_things(sbox
):
433 "reverse update switched wc things to an older rev"
438 # Setup some switched things (don't bother verifying)
439 do_routine_switching(wc_dir
, sbox
.repo_url
, 0)
441 # Commit some stuff (don't bother verifying)
442 commit_routine_switching(wc_dir
, 0)
444 # Some convenient path variables
445 iota_path
= os
.path
.join(wc_dir
, 'iota')
446 B_path
= os
.path
.join(wc_dir
, 'A', 'B')
448 # Update to HEAD (tested elsewhere)
449 svntest
.main
.run_svn(None, 'up', wc_dir
)
451 # Now, reverse update, back to the pre-commit state.
452 expected_output
= svntest
.wc
.State(wc_dir
, {
453 'iota' : Item(status
='U '),
454 'A/B/pi' : Item(status
='U '),
455 'A/B/Z' : Item(status
='D '),
458 # Create expected disk tree
459 expected_disk
= get_routine_disk_state(wc_dir
)
460 expected_disk
.tweak('A/D/gamma', contents
="This is the file 'gamma'.\napple")
461 expected_disk
.tweak('A/D/G/pi', contents
="This is the file 'pi'.\nmelon")
464 'A/D/G/Z/zeta' : Item("This is the file 'zeta'.\n"),
467 # Create expected status tree for the update.
468 expected_status
= get_routine_status_state(wc_dir
)
469 expected_status
.tweak(wc_rev
=2)
470 expected_status
.tweak('iota', 'A/B', switched
='S')
471 expected_status
.tweak('A/B', 'A/B/pi', 'A/B/rho', 'A/B/tau', 'iota',
473 expected_status
.add({
474 'A/D/G/Z' : Item(status
=' ', wc_rev
=2),
475 'A/D/G/Z/zeta' : Item(status
=' ', wc_rev
=2),
478 svntest
.actions
.run_and_verify_update(wc_dir
,
489 #----------------------------------------------------------------------
491 def log_switched_file(sbox
):
492 "show logs for a switched file"
497 # Setup some switched things (don't bother verifying)
498 do_routine_switching(wc_dir
, sbox
.repo_url
, 0)
500 # edit and commit switched file 'iota'
501 iota_path
= os
.path
.join(wc_dir
, 'iota')
502 svntest
.main
.run_svn(None, 'ps', 'x', 'x', iota_path
)
503 svntest
.main
.run_svn(None,
505 'set prop on switched iota',
508 # log switched file 'iota'
509 output
, error
= svntest
.main
.run_svn(None, 'log', iota_path
)
511 if line
.find("set prop on switched iota") != -1:
514 raise svntest
.Failure
516 #----------------------------------------------------------------------
518 def relocate_deleted_missing_copied(sbox
):
519 "relocate with deleted, missing and copied entries"
523 # Delete A/mu to create a deleted entry for mu in A/.svn/entries
524 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
525 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', mu_path
)
526 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
527 expected_status
.remove('A/mu')
528 expected_output
= svntest
.wc
.State(wc_dir
, {
529 'A/mu' : Item(verb
='Deleting'),
531 svntest
.actions
.run_and_verify_commit(wc_dir
,
534 None, None, None, None, None,
537 # Remove A/B/F to create a missing entry
538 svntest
.main
.safe_rmtree(os
.path
.join(wc_dir
, 'A', 'B', 'F'))
540 # Copy A/D/H to A/D/H2
541 H_path
= os
.path
.join(wc_dir
, 'A', 'D', 'H')
542 H2_path
= os
.path
.join(wc_dir
, 'A', 'D', 'H2')
543 svntest
.actions
.run_and_verify_svn(None, None, [], 'copy',
545 expected_status
.add({
546 'A/D/H2' : Item(status
='A ', wc_rev
='-', copied
='+'),
547 'A/D/H2/chi' : Item(status
=' ', wc_rev
='-', copied
='+'),
548 'A/D/H2/omega' : Item(status
=' ', wc_rev
='-', copied
='+'),
549 'A/D/H2/psi' : Item(status
=' ', wc_rev
='-', copied
='+'),
551 expected_status
.tweak('A/B/F', status
='! ', wc_rev
='?')
552 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
555 repo_dir
= sbox
.repo_dir
556 repo_url
= sbox
.repo_url
557 other_repo_dir
, other_repo_url
= sbox
.add_repo_path('other')
558 svntest
.main
.copy_repos(repo_dir
, other_repo_dir
, 2, 0)
559 svntest
.main
.safe_rmtree(repo_dir
, 1)
560 svntest
.actions
.run_and_verify_svn(None, None, [], 'switch', '--relocate',
561 repo_url
, other_repo_url
, wc_dir
)
563 # Deleted and missing entries should be preserved, so update should
564 # show only A/B/F being reinstated
565 expected_output
= svntest
.wc
.State(wc_dir
, {
566 'A/B/F' : Item(status
='A '),
568 expected_disk
= svntest
.main
.greek_state
.copy()
569 expected_disk
.remove('A/mu')
572 'A/D/H2/chi' : Item("This is the file 'chi'.\n"),
573 'A/D/H2/omega' : Item("This is the file 'omega'.\n"),
574 'A/D/H2/psi' : Item("This is the file 'psi'.\n"),
576 expected_status
.add({
577 'A/B/F' : Item(status
=' ', wc_rev
='2'),
579 expected_status
.tweak(wc_rev
=2)
580 expected_status
.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi',
582 svntest
.actions
.run_and_verify_update(wc_dir
,
587 # Commit to verify that copyfrom URLs have been relocated
588 expected_output
= svntest
.wc
.State(wc_dir
, {
589 'A/D/H2' : Item(verb
='Adding'),
591 expected_status
.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi',
592 status
=' ', wc_rev
='3', copied
=None)
593 svntest
.actions
.run_and_verify_commit(wc_dir
,
594 expected_output
, expected_status
,
595 None, None, None, None, None,
599 #----------------------------------------------------------------------
601 def delete_subdir(sbox
):
602 "switch that deletes a sub-directory"
606 A_path
= os
.path
.join(wc_dir
, 'A')
607 A_url
= sbox
.repo_url
+ '/A'
608 A2_url
= sbox
.repo_url
+ '/A2'
609 A2_B_F_url
= sbox
.repo_url
+ '/A2/B/F'
611 svntest
.actions
.run_and_verify_svn(None,
612 ['\n', 'Committed revision 2.\n'], [],
613 'cp', '-m', 'make copy', A_url
, A2_url
)
615 svntest
.actions
.run_and_verify_svn(None,
616 ['\n', 'Committed revision 3.\n'], [],
617 'rm', '-m', 'delete subdir', A2_B_F_url
)
619 expected_output
= svntest
.wc
.State(wc_dir
, {
620 'A' : Item(status
=' U'),
621 'A/B/F' : Item(status
='D '),
623 expected_disk
= svntest
.main
.greek_state
.copy()
624 expected_disk
.remove('A/B/F')
625 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 3)
626 expected_status
.tweak('A', switched
='S')
627 expected_status
.remove('A/B/F')
628 expected_status
.tweak('', 'iota', wc_rev
=1)
630 # Used to fail with a 'directory not locked' error for A/B/F
631 svntest
.actions
.run_and_verify_switch(wc_dir
, A_path
, A2_url
,
636 #----------------------------------------------------------------------
637 # Issue 1532: Switch a file to a dir: can't switch it back to the file
639 def file_dir_file(sbox
):
640 "switch a file to a dir and back to the file"
644 file_path
= os
.path
.join(wc_dir
, 'iota')
645 file_url
= sbox
.repo_url
+ '/iota'
646 dir_url
= sbox
.repo_url
+ '/A/C'
648 svntest
.actions
.run_and_verify_svn(None, None, [],
649 'switch', dir_url
, file_path
)
651 svntest
.actions
.run_and_verify_svn(None, None, [],
652 'switch', file_url
, file_path
)
654 #----------------------------------------------------------------------
655 # Issue 1751: "svn switch --non-recursive" does not switch existing files,
656 # and generates the wrong URL for new files.
658 def nonrecursive_switching(sbox
):
659 "non-recursive switch"
661 wc1_dir
= sbox
.wc_dir
662 wc2_dir
= os
.path
.join(wc1_dir
, 'wc2')
664 # "Trunk" will be the existing dir "A/", with existing file "mu".
665 # "Branch" will be the new dir "branch/version1/", with added file "newfile".
666 # "wc1" will hold the whole repository (including trunk and branch).
667 # "wc2" will hold the "trunk" and then be switched to the "branch".
668 # It is irrelevant that wc2 is located on disk as a sub-directory of wc1.
669 trunk_url
= sbox
.repo_url
+ '/A'
670 branch_url
= sbox
.repo_url
+ '/branch'
671 version1_url
= branch_url
+ '/version1'
672 wc1_new_file
= os
.path
.join(wc1_dir
, 'branch', 'version1', 'newfile')
673 wc2_new_file
= os
.path
.join(wc2_dir
, 'newfile')
674 wc2_mu_file
= os
.path
.join(wc2_dir
, 'mu')
675 wc2_B_dir
= os
.path
.join(wc2_dir
, 'B')
676 wc2_C_dir
= os
.path
.join(wc2_dir
, 'C')
677 wc2_D_dir
= os
.path
.join(wc2_dir
, 'D')
679 # Check out the trunk as "wc2"
680 svntest
.main
.run_svn(None, 'co', trunk_url
, wc2_dir
)
682 # Make a branch, and add a new file, in "wc_dir" and repository
683 svntest
.main
.run_svn(None,
684 'mkdir', '-m', '', branch_url
)
685 svntest
.main
.run_svn(None,
686 'cp', '-m', '', trunk_url
, version1_url
)
687 svntest
.main
.run_svn(None,
689 svntest
.main
.file_append(wc1_new_file
, "This is the file 'newfile'.\n")
690 svntest
.main
.run_svn(None, 'add', wc1_new_file
)
691 svntest
.main
.run_svn(None, 'ci', '-m', '', wc1_dir
)
693 # Try to switch "wc2" to the branch (non-recursively)
694 svntest
.actions
.run_and_verify_svn(None, None, [],
695 'switch', '-N', version1_url
, wc2_dir
)
697 # Check the URLs of the (not switched) directories.
698 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
700 if out
[1].find('/A/B') == -1:
702 raise svntest
.Failure
704 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
706 if out
[1].find('/A/C') == -1:
708 raise svntest
.Failure
710 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
712 if out
[1].find('/A/D') == -1:
714 raise svntest
.Failure
716 # Check the URLs of the switched files.
717 # ("svn status -u" might be a better check: it fails when newfile's URL
718 # is bad, and shows "S" when mu's URL is wrong.)
720 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
722 if out
[2].find('/branch/version1/mu') == -1:
724 raise svntest
.Failure
726 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
727 'info', wc2_new_file
)
728 if out
[2].find('/branch/version1/newfile') == -1:
730 raise svntest
.Failure
733 #----------------------------------------------------------------------
734 def failed_anchor_is_target(sbox
):
735 "anchor=target that fails due to local mods"
739 G_url
= sbox
.repo_url
+ '/A/D/G'
740 G_psi_url
= G_url
+ '/psi'
741 svntest
.actions
.run_and_verify_svn(None,
742 ['\n', 'Committed revision 2.\n'], [],
743 'mkdir', '-m', 'log msg', G_psi_url
)
745 H_path
= os
.path
.join(wc_dir
, 'A', 'D', 'H')
746 psi_path
= os
.path
.join(H_path
, 'psi')
747 svntest
.main
.file_append(psi_path
, "more text")
749 # This switch leaves psi unversioned, because of the local mods,
750 # then fails because it tries to add a directory of the same name.
751 out
, err
= svntest
.main
.run_svn(1, 'switch',
754 raise svntest
.Failure
756 # Some items under H show up as switched because, while H itself was
757 # switched, the switch command failed before it reached all items
759 # NOTE: I suspect this whole test is dependent on the order in
760 # which changes are received, but since the new psi is a dir, it
761 # appears we can count on it being received last. But if this test
762 # ever starts failing, you read it here first :-).
763 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
764 expected_status
.tweak('A/D/H', status
='! ', switched
='S', wc_rev
=2)
765 expected_status
.remove('A/D/H/psi', 'A/D/H/chi', 'A/D/H/omega')
766 expected_status
.add({
767 'A/D/H/pi' : Item(status
=' ', wc_rev
=2),
768 'A/D/H/tau' : Item(status
=' ', wc_rev
=2),
769 'A/D/H/rho' : Item(status
=' ', wc_rev
=2),
771 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
773 # There was a bug whereby the failed switch left the wrong URL in
774 # the target directory H. Check for that.
775 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [], 'info', H_path
)
777 if line
.find('URL: ' + G_url
) != -1:
780 raise svntest
.Failure
782 # Remove the now-unversioned psi, and repeat the switch. This
783 # should complete the switch.
785 svntest
.actions
.run_and_verify_svn(None, None, [], 'switch',
788 expected_status
.tweak('A/D/H', status
=' ') # remains switched
789 expected_status
.add({ 'A/D/H/psi' : Item(status
=' ',
792 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
794 #----------------------------------------------------------------------
795 # Issue #1826 - svn switch temporarily drops invalid URLs into the entries
796 # files (which become not-temporary if the switch fails).
797 def bad_intermediate_urls(sbox
):
798 "bad intermediate urls in use"
802 # We'll be switching our working copy to (a modified) A/C in the Greek tree.
804 # First, make an extra subdirectory in C to match one in the root, plus
805 # another one inside of that.
806 C_url
= sbox
.repo_url
+ '/A/C'
807 C_A_url
= sbox
.repo_url
+ '/A/C/A'
808 C_A_Z_url
= sbox
.repo_url
+ '/A/C/A/Z'
809 svntest
.actions
.run_and_verify_svn(None,
810 ['\n', 'Committed revision 2.\n'], [],
811 'mkdir', '-m', 'log msg',
814 # Now, we'll drop a conflicting path under the root.
815 A_path
= os
.path
.join(wc_dir
, 'A')
816 A_Z_path
= os
.path
.join(A_path
, 'Z')
817 svntest
.main
.file_append(A_Z_path
, 'Look, Mom, no ... switch success.')
819 # This switch should fail for reasons of obstruction.
820 out
, err
= svntest
.main
.run_svn(1, 'switch',
823 raise svntest
.Failure
825 # However, the URL for A should now reflect A/C/A, not something else.
826 out
, err
= svntest
.actions
.run_and_verify_svn(None, None, [],
828 if out
[1].find('/A/C/A') == -1:
829 raise svntest
.Failure
833 #----------------------------------------------------------------------
834 # Regression test for issue #1825: failed switch may corrupt
837 def obstructed_switch(sbox
):
842 E_url
= sbox
.repo_url
+ '/A/B/E'
843 E_url2
= sbox
.repo_url
+ '/A/B/Esave'
844 svntest
.actions
.run_and_verify_svn(None,
845 ['\n', 'Committed revision 2.\n'], [],
846 'cp', '-m', 'msgcopy', E_url
, E_url2
)
848 E_path
= os
.path
.join(wc_dir
, 'A', 'B', 'E')
849 alpha_path
= os
.path
.join(E_path
, 'alpha')
850 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', alpha_path
)
851 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
852 expected_status
.remove('A/B/E/alpha')
853 expected_output
= svntest
.wc
.State(wc_dir
, {
854 'A/B/E/alpha' : Item(verb
='Deleting'),
856 svntest
.actions
.run_and_verify_commit(wc_dir
,
857 expected_output
, expected_status
,
858 None, None, None, None, None,
861 svntest
.main
.file_append(alpha_path
, "hello")
862 out
, err
= svntest
.main
.run_svn(1,
863 'sw', E_url2
, E_path
)
865 if line
.find("object of the same name already exists") != -1:
868 raise svntest
.Failure
870 os
.remove(alpha_path
)
871 svntest
.actions
.run_and_verify_svn(None, None, [], 'sw', E_url2
, E_path
)
872 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
873 expected_status
.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', wc_rev
=3)
874 expected_status
.tweak('A/B/E', switched
='S')
875 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
878 #----------------------------------------------------------------------
880 def commit_mods_below_switch(sbox
):
881 "commit with mods below switch"
885 C_path
= os
.path
.join(wc_dir
, 'A', 'C')
886 B_url
= sbox
.repo_url
+ '/A/B'
887 expected_output
= svntest
.wc
.State(wc_dir
, {
888 'A/C/E' : Item(status
='A '),
889 'A/C/E/alpha' : Item(status
='A '),
890 'A/C/E/beta' : Item(status
='A '),
891 'A/C/F' : Item(status
='A '),
892 'A/C/lambda' : Item(status
='A '),
894 expected_disk
= svntest
.main
.greek_state
.copy()
897 'A/C/E/alpha' : Item(contents
="This is the file 'alpha'.\n"),
898 'A/C/E/beta' : Item(contents
="This is the file 'beta'.\n"),
900 'A/C/lambda' : Item(contents
="This is the file 'lambda'.\n"),
902 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
903 expected_status
.tweak('A/C', switched
='S')
904 expected_status
.add({
905 'A/C/E' : Item(status
=' ', wc_rev
=1),
906 'A/C/E/alpha' : Item(status
=' ', wc_rev
=1),
907 'A/C/E/beta' : Item(status
=' ', wc_rev
=1),
908 'A/C/F' : Item(status
=' ', wc_rev
=1),
909 'A/C/lambda' : Item(status
=' ', wc_rev
=1),
911 svntest
.actions
.run_and_verify_switch(wc_dir
, C_path
, B_url
,
916 D_path
= os
.path
.join(wc_dir
, 'A', 'D')
917 svntest
.actions
.run_and_verify_svn(None, None, [],
918 'propset', 'x', 'x', C_path
, D_path
)
920 expected_status
.tweak('A/C', 'A/D', status
=' M')
921 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
923 expected_output
= svntest
.wc
.State(wc_dir
, {
924 'A/C' : Item(verb
='Sending'),
925 'A/D' : Item(verb
='Sending'),
927 expected_status
.tweak('A/C', 'A/D', status
=' ', wc_rev
=2)
929 # A/C erroneously classified as a wc root caused the commit to fail
930 # with "'A/C/E' is missing or not locked"
931 svntest
.actions
.run_and_verify_commit(wc_dir
,
932 expected_output
, expected_status
,
933 None, None, None, None, None,
936 def relocate_beyond_repos_root(sbox
):
937 "relocate with prefixes longer than repo root"
941 repo_dir
= sbox
.repo_dir
942 repo_url
= sbox
.repo_url
943 other_repo_dir
, other_repo_url
= sbox
.add_repo_path('other')
944 svntest
.main
.copy_repos(repo_dir
, other_repo_dir
, 1, 0)
945 svntest
.main
.safe_rmtree(repo_dir
, 1)
947 A_url
= repo_url
+ "/A"
948 other_A_url
= other_repo_url
+ "/A"
949 other_B_url
= other_repo_url
+ "/B"
950 A_wc_dir
= os
.path
.join(wc_dir
, "A")
952 # A relocate that changes the repo path part of the URL shouldn't work.
953 # This tests for issue #2380.
954 svntest
.actions
.run_and_verify_svn(None, None,
955 ".*can only change the repository part.*",
956 'switch', '--relocate',
957 A_url
, other_B_url
, A_wc_dir
)
959 # Another way of trying to change the fs path, leading to an invalid
961 svntest
.actions
.run_and_verify_svn(None, None,
962 ".*is not the root.*",
963 'switch', '--relocate',
964 repo_url
, other_B_url
, A_wc_dir
)
966 svntest
.actions
.run_and_verify_svn(None, None, [],
967 'switch', '--relocate',
968 A_url
, other_A_url
, A_wc_dir
)
970 # Check that we can contact the repository, meaning that the
971 # relocate actually changed the URI. Escape the expected URI to
972 # avoid problems from any regex meta-characters it may contain
974 escaped_exp
= '^URL: ' + re
.escape(other_A_url
) + '$' \
975 '|Path.+|Repository.+|Revision.+|Node.+|Last.+|\n'
976 svntest
.actions
.run_and_verify_svn(None, escaped_exp
, [],
977 'info', '-rHEAD', A_wc_dir
)
979 #----------------------------------------------------------------------
981 def refresh_read_only_attribute(sbox
):
982 "refresh the WC file system read-only attribute "
984 # This test will fail when run as root. Since that's normal behavior, just skip
986 if os
.name
== 'posix':
987 if os
.geteuid() == 0:
994 url
= sbox
.repo_url
+ '/A'
995 branch_url
= sbox
.repo_url
+ '/A-branch'
996 svntest
.actions
.run_and_verify_svn(None,
997 ['\n', 'Committed revision 2.\n'], [],
998 'cp', '-m', 'svn:needs-lock not set',
1001 # Set the svn:needs-lock property on a file from the "trunk".
1002 A_path
= os
.path
.join(wc_dir
, 'A')
1003 mu_path
= os
.path
.join(A_path
, 'mu')
1004 svntest
.actions
.run_and_verify_svn(None, None, [],
1005 'ps', 'svn:needs-lock', '1', mu_path
)
1007 # Commit the propset of svn:needs-lock.
1008 expected_output
= svntest
.wc
.State(wc_dir
, {
1009 'A/mu' : Item(verb
='Sending'),
1011 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1012 expected_status
.tweak('A/mu', wc_rev
=3)
1013 svntest
.actions
.run_and_verify_commit(wc_dir
,
1014 expected_output
, expected_status
,
1015 None, None, None, None, None,
1018 # The file on which svn:needs-lock was set is now expected to be read-only.
1019 if os
.access(mu_path
, os
.W_OK
):
1020 raise svntest
.Failure("'%s' expected to be read-only after having had "
1021 "its svn:needs-lock property set" % mu_path
)
1023 # Switch to the branch with the WC state from before the propset of
1025 expected_output
= svntest
.wc
.State(wc_dir
, {
1026 'A' : Item(status
=' U'),
1027 'A/mu' : Item(status
=' U'),
1029 expected_disk
= svntest
.main
.greek_state
.copy()
1030 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 3)
1031 expected_status
.tweak('', wc_rev
=1)
1032 expected_status
.tweak('iota', wc_rev
=1)
1033 expected_status
.tweak('A', switched
='S')
1034 svntest
.actions
.run_and_verify_switch(wc_dir
, A_path
, branch_url
,
1039 # The file with we set svn:needs-lock on should now be writable, but
1040 # is still read-only!
1041 if not os
.access(mu_path
, os
.W_OK
):
1042 raise svntest
.Failure("'%s' expected to be writable after being switched "
1043 "to a branch on which its svn:needs-lock property "
1044 "is not set" % mu_path
)
1046 # Check that switch can't change the repository root.
1047 def switch_change_repos_root(sbox
):
1048 "switch shouldn't allow changing repos root"
1051 wc_dir
= sbox
.wc_dir
1052 repo_url
= sbox
.repo_url
1053 other_repo_url
= repo_url
1055 # Strip trailing slashes and add something bogus to that other URL.
1056 while other_repo_url
[-1] == '/':
1057 other_repos_url
= other_repo_url
[:-1]
1058 other_repo_url
= other_repo_url
+ "_bogus"
1060 other_A_url
= other_repo_url
+ "/A"
1061 A_wc_dir
= os
.path
.join(wc_dir
, "A")
1063 # Test 1: A switch that changes to a non-existing repo shouldn't work.
1064 expected_err
= ".*Unable to open repository.*|.*Could not open.*|"\
1065 ".*No repository found.*"
1066 svntest
.actions
.run_and_verify_svn(None, None,
1069 other_A_url
, A_wc_dir
)
1071 # Test 2: A switch that changes the repo root part of the URL shouldn't work.
1072 other_repo_dir
, other_repo_url
= sbox
.add_repo_path('other')
1073 other_A_url
= other_repo_url
+ "/A"
1075 svntest
.main
.create_repos(other_repo_dir
)
1076 svntest
.actions
.run_and_verify_svn(None, None,
1077 ".*not the same repository.*",
1079 other_A_url
, A_wc_dir
)
1081 # Make sure we didn't break the WC.
1082 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1083 svntest
.actions
.run_and_verify_status(wc_dir
, expected_status
)
1086 def relocate_and_propset(sbox
):
1087 "out of date propset should fail after a relocate"
1089 # Create virgin repos and working copy
1090 svntest
.main
.safe_rmtree(sbox
.repo_dir
, 1)
1091 svntest
.main
.create_repos(sbox
.repo_dir
)
1093 wc_dir
= sbox
.wc_dir
1094 repo_dir
= sbox
.repo_dir
1095 repo_url
= sbox
.repo_url
1097 # import the greek tree
1098 svntest
.main
.greek_state
.write_to_disk(svntest
.main
.greek_dump_dir
)
1099 output
, errput
= svntest
.main
.run_svn(None, 'import',
1100 '-m', 'Log message for revision 1.',
1101 svntest
.main
.greek_dump_dir
, sbox
.repo_url
)
1104 svntest
.main
.safe_rmtree(wc_dir
, 1)
1105 svntest
.actions
.run_and_verify_svn(None,
1111 other_repo_dir
, other_repo_url
= sbox
.add_repo_path('other')
1112 svntest
.main
.copy_repos(repo_dir
, other_repo_dir
, 1, 0)
1113 svntest
.main
.safe_rmtree(repo_dir
, 1)
1114 svntest
.actions
.run_and_verify_svn(None, None, [], 'switch', '--relocate',
1115 repo_url
, other_repo_url
, wc_dir
)
1117 # Remove gamma from the working copy.
1118 D_path
= os
.path
.join(wc_dir
, 'A', 'D')
1119 gamma_path
= os
.path
.join(wc_dir
, 'A', 'D', 'gamma')
1120 svntest
.main
.run_svn(None, 'rm', gamma_path
)
1122 # Create expected commit output.
1123 expected_output
= svntest
.wc
.State(wc_dir
, {
1124 'A/D/gamma' : Item(verb
='Deleting'),
1127 # After committing, status should show no sign of gamma.
1128 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1129 expected_status
.remove('A/D/gamma')
1131 # Commit the deletion of gamma and verify.
1132 svntest
.actions
.run_and_verify_commit(wc_dir
,
1135 None, None, None, None, None,
1138 # Now gamma should be marked as `deleted' under the hood, at
1139 # revision 2. Meanwhile, A/D is still lagging at revision 1.
1141 # Make a propchange on A/D
1142 svntest
.main
.run_svn(None, 'ps', 'foo', 'bar', D_path
)
1144 # Commit and *expect* a repository Merge failure:
1145 svntest
.actions
.run_and_verify_commit(wc_dir
,
1153 #----------------------------------------------------------------------
1155 def forced_switch(sbox
):
1156 "forced switch tolerates obstructions to adds"
1160 G_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'G')
1163 # Faux file obstructions
1164 shutil
.copyfile(os
.path
.join(sbox
.wc_dir
, 'A', 'D', 'gamma'),
1165 os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'gamma'))
1166 shutil
.copyfile(os
.path
.join(sbox
.wc_dir
, 'A', 'D', 'G', 'tau'),
1167 os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'G', 'tau'))
1169 # Real file obstruction
1170 pi_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'G', 'pi')
1171 svntest
.main
.file_write(pi_path
,
1172 "This is the OBSTRUCTING file 'pi'.\n")
1174 # Non-obstructing dir and file
1175 I_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'I')
1177 upsilon_path
= os
.path
.join(G_path
, 'upsilon')
1178 svntest
.main
.file_write(upsilon_path
,
1179 "This is the unversioned file 'upsilon'.\n")
1181 # Setup expected results of switch.
1182 expected_output
= svntest
.wc
.State(sbox
.wc_dir
, {
1183 "A/B/F/gamma" : Item(status
='E '),
1184 "A/B/F/G" : Item(status
='E '),
1185 "A/B/F/G/pi" : Item(status
='E '),
1186 "A/B/F/G/rho" : Item(status
='A '),
1187 "A/B/F/G/tau" : Item(status
='E '),
1188 "A/B/F/H" : Item(status
='A '),
1189 "A/B/F/H/chi" : Item(status
='A '),
1190 "A/B/F/H/omega" : Item(status
='A '),
1191 "A/B/F/H/psi" : Item(status
='A '),
1193 expected_disk
= svntest
.main
.greek_state
.copy()
1195 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
1197 "A/B/F/G/pi" : Item("This is the OBSTRUCTING file 'pi'.\n"),
1198 "A/B/F/G/rho" : Item("This is the file 'rho'.\n"),
1199 "A/B/F/G/tau" : Item("This is the file 'tau'.\n"),
1200 "A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"),
1202 "A/B/F/H/chi" : Item("This is the file 'chi'.\n"),
1203 "A/B/F/H/omega" : Item("This is the file 'omega'.\n"),
1204 "A/B/F/H/psi" : Item("This is the file 'psi'.\n"),
1207 expected_status
= svntest
.actions
.get_virginal_state(sbox
.wc_dir
, 1)
1208 expected_status
.tweak('A/B/F', switched
='S')
1209 expected_status
.add({
1210 "A/B/F/gamma" : Item(status
=' ', wc_rev
=1),
1211 "A/B/F/G" : Item(status
=' ', wc_rev
=1),
1212 "A/B/F/G/pi" : Item(status
='M ', wc_rev
=1),
1213 "A/B/F/G/rho" : Item(status
=' ', wc_rev
=1),
1214 "A/B/F/G/tau" : Item(status
=' ', wc_rev
=1),
1215 "A/B/F/H" : Item(status
=' ', wc_rev
=1),
1216 "A/B/F/H/chi" : Item(status
=' ', wc_rev
=1),
1217 "A/B/F/H/omega" : Item(status
=' ', wc_rev
=1),
1218 "A/B/F/H/psi" : Item(status
=' ', wc_rev
=1),
1221 # Do the switch and check the results in three ways.
1222 F_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F')
1223 AD_url
= sbox
.repo_url
+ '/A/D'
1224 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
, F_path
, AD_url
,
1227 expected_status
, None,
1228 None, None, None, None, 0,
1231 #----------------------------------------------------------------------
1233 def forced_switch_failures(sbox
):
1234 "forced switch fails with some types of obstuctions"
1237 # Add a directory to obstruct a file.
1238 pi_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'pi')
1241 # Add a file to obstruct a directory.
1242 H_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'C', 'H')
1243 svntest
.main
.file_write(H_path
, "The file 'H'\n")
1245 # Test three cases where forced switch should fail:
1247 # 1) A forced switch that tries to add a file when an unversioned
1248 # directory of the same name already exists should fail.
1249 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
,
1250 os
.path
.join(sbox
.wc_dir
, 'A', 'C'),
1251 sbox
.repo_url
+ "/A/D",
1253 ".*Failed to add directory .*" + \
1254 ": a non-directory object of the" + \
1255 " same name already exists\n",
1256 None, None, None, None, 0, '--force')
1258 # 2) A forced switch that tries to add a dir when a file of the same
1259 # name already exists should fail.
1260 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
,
1261 os
.path
.join(sbox
.wc_dir
,
1263 sbox
.repo_url
+ "/A/D/G",
1265 ".*Failed to add file .*" + \
1266 ": a non-file object of the " + \
1267 "same name already exists\n",
1268 None, None, None, None, 0, '--force')
1270 # 3) A forced update that tries to add a directory when a versioned
1271 # directory of the same name already exists should fail.
1273 # Make dir A/D/H/I in repos.
1274 I_url
= sbox
.repo_url
+ "/A/D/H/I"
1275 so
, se
= svntest
.actions
.run_and_verify_svn("Unexpected error during mkdir",
1276 ['\n', 'Committed revision 2.\n'],
1279 "-m", "Log Message")
1281 # Make A/D/G/I and co A/D/H/I into it.
1282 I_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'D', 'G', 'I')
1284 so
, se
= svntest
.actions
.run_and_verify_svn("Unexpected error during co",
1285 ['Checked out revision 2.\n'],
1287 "co", I_url
, I_path
)
1289 # Try the forced switch. A/D/G/I obstructs the dir A/D/G/I coming
1290 # from the repos. Normally this isn't a problem, but A/D/G/I is already
1291 # versioned so this should fail.
1292 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
,
1293 os
.path
.join(sbox
.wc_dir
,
1295 sbox
.repo_url
+ "/A/D/H",
1297 ".*Failed to add " + \
1298 "directory .*: a versioned " + \
1299 "directory of the same name " + \
1301 None, None, None, None, 0, '--force')
1303 def switch_with_obstructing_local_adds(sbox
):
1304 "switch tolerates WC adds"
1307 # Dir obstruction scheduled for addition without history.
1308 G_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'G')
1311 # File obstructions scheduled for addition without history.
1312 # Contents identical to additions from switch.
1313 gamma_copy_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'gamma')
1314 shutil
.copyfile(os
.path
.join(sbox
.wc_dir
, 'A', 'D', 'gamma'),
1316 shutil
.copyfile(os
.path
.join(sbox
.wc_dir
, 'A', 'D', 'G', 'tau'),
1317 os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'G', 'tau'))
1319 # File obstruction scheduled for addition without history.
1320 # Contents conflict with addition from switch.
1321 pi_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'G', 'pi')
1322 svntest
.main
.file_write(pi_path
,
1323 "This is the OBSTRUCTING file 'pi'.\n")
1325 # Non-obstructing dir and file scheduled for addition without history.
1326 I_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F', 'I')
1328 upsilon_path
= os
.path
.join(G_path
, 'upsilon')
1329 svntest
.main
.file_write(upsilon_path
,
1330 "This is the unversioned file 'upsilon'.\n")
1332 # Add the above obstructions.
1333 svntest
.actions
.run_and_verify_svn("Add error:", None, [],
1334 'add', G_path
, I_path
,
1337 # Setup expected results of switch.
1338 expected_output
= svntest
.wc
.State(sbox
.wc_dir
, {
1339 "A/B/F/gamma" : Item(status
='E '),
1340 "A/B/F/G" : Item(status
='E '),
1341 "A/B/F/G/pi" : Item(status
='C '),
1342 "A/B/F/G/rho" : Item(status
='A '),
1343 "A/B/F/G/tau" : Item(status
='E '),
1344 "A/B/F/H" : Item(status
='A '),
1345 "A/B/F/H/chi" : Item(status
='A '),
1346 "A/B/F/H/omega" : Item(status
='A '),
1347 "A/B/F/H/psi" : Item(status
='A '),
1350 expected_disk
= svntest
.main
.greek_state
.copy()
1352 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
1354 "A/B/F/G/pi" : Item("\n".join(["<<<<<<< .mine",
1355 "This is the OBSTRUCTING file 'pi'.",
1357 "This is the file 'pi'.",
1360 "A/B/F/G/rho" : Item("This is the file 'rho'.\n"),
1361 "A/B/F/G/tau" : Item("This is the file 'tau'.\n"),
1362 "A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"),
1364 "A/B/F/H/chi" : Item("This is the file 'chi'.\n"),
1365 "A/B/F/H/omega" : Item("This is the file 'omega'.\n"),
1366 "A/B/F/H/psi" : Item("This is the file 'psi'.\n"),
1369 expected_status
= svntest
.actions
.get_virginal_state(sbox
.wc_dir
, 1)
1370 expected_status
.tweak('A/B/F', switched
='S')
1371 expected_status
.add({
1372 "A/B/F/gamma" : Item(status
=' ', wc_rev
=1),
1373 "A/B/F/G" : Item(status
=' ', wc_rev
=1),
1374 "A/B/F/G/pi" : Item(status
='C ', wc_rev
=1),
1375 "A/B/F/G/rho" : Item(status
=' ', wc_rev
=1),
1376 "A/B/F/G/tau" : Item(status
=' ', wc_rev
=1),
1377 "A/B/F/G/upsilon" : Item(status
='A ', wc_rev
=0),
1378 "A/B/F/H" : Item(status
=' ', wc_rev
=1),
1379 "A/B/F/H/chi" : Item(status
=' ', wc_rev
=1),
1380 "A/B/F/H/omega" : Item(status
=' ', wc_rev
=1),
1381 "A/B/F/H/psi" : Item(status
=' ', wc_rev
=1),
1382 "A/B/F/I" : Item(status
='A ', wc_rev
=0),
1385 # "Extra" files that we expect to result from the conflicts.
1386 extra_files
= ['pi\.r0', 'pi\.r1', 'pi\.mine']
1388 # Do the switch and check the results in three ways.
1389 F_path
= os
.path
.join(sbox
.wc_dir
, 'A', 'B', 'F')
1390 D_url
= sbox
.repo_url
+ '/A/D'
1392 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
, F_path
, D_url
,
1397 svntest
.tree
.detect_conflict_files
,
1398 extra_files
, None, None, 0)
1400 #----------------------------------------------------------------------
1402 def switch_scheduled_add(sbox
):
1403 "switch a scheduled-add file"
1405 wc_dir
= sbox
.wc_dir
1407 file_path
= os
.path
.join(wc_dir
, 'stub_file')
1408 switch_url
= sbox
.repo_url
+ '/iota'
1410 svntest
.main
.file_append(file_path
, "")
1411 svntest
.actions
.run_and_verify_svn(None, None, [],
1413 svntest
.actions
.run_and_verify_svn(None, None, [],
1414 'switch', switch_url
, file_path
)
1416 #----------------------------------------------------------------------
1418 def mergeinfo_switch_elision(sbox
):
1419 "mergeinfo does not elide post switch"
1421 # When a switch adds mergeinfo on a path which is identical to
1422 # the mergeinfo on one of the path's subtrees, the subtree's mergeinfo
1423 # should *not* elide! If it did this could result in the switch of a
1424 # pristine tree producing local mods.
1426 # Search for the comment entitled "The Merge Kluge" in merge_tests.py
1427 # to understand why we shorten, and subsequently chdir() after calling
1429 def shorten_path_kludge(path
):
1430 shorten_by
= len(svntest
.main
.work_dir
) + len(os
.sep
)
1431 return path
[shorten_by
:]
1434 wc_dir
= sbox
.wc_dir
1436 # Some paths we'll care about
1437 lambda_path
= os
.path
.join(wc_dir
, "A", "B_COPY_1", "lambda")
1438 B_COPY_1_path
= os
.path
.join(wc_dir
, "A", "B_COPY_1")
1439 B_COPY_2_path
= os
.path
.join(wc_dir
, "A", "B_COPY_2")
1440 E_COPY_2_path
= os
.path
.join(wc_dir
, "A", "B_COPY_2", "E")
1441 alpha_path
= os
.path
.join(wc_dir
, "A", "B", "E", "alpha")
1442 beta_path
= os
.path
.join(wc_dir
, "A", "B", "E", "beta")
1444 # Make branches A/B_COPY_1 and A/B_COPY_2
1445 svntest
.actions
.run_and_verify_svn(
1447 ["A " + os
.path
.join(wc_dir
, "A", "B_COPY_1", "lambda") + "\n",
1448 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_1", "E") + "\n",
1449 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_1", "E", "alpha") + "\n",
1450 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_1", "E", "beta") + "\n",
1451 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_1", "F") + "\n",
1452 "Checked out revision 1.\n",
1453 "A " + B_COPY_1_path
+ "\n"],
1456 sbox
.repo_url
+ "/A/B",
1459 svntest
.actions
.run_and_verify_svn(
1461 ["A " + os
.path
.join(wc_dir
, "A", "B_COPY_2", "lambda") + "\n",
1462 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_2", "E") + "\n",
1463 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_2", "E", "alpha") + "\n",
1464 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_2", "E", "beta") + "\n",
1465 "A " + os
.path
.join(wc_dir
, "A", "B_COPY_2", "F") + "\n",
1466 "Checked out revision 1.\n",
1467 "A " + B_COPY_2_path
+ "\n"],
1470 sbox
.repo_url
+ "/A/B",
1473 expected_output
= svntest
.wc
.State(wc_dir
, {
1474 'A/B_COPY_1' : Item(verb
='Adding'),
1475 'A/B_COPY_2' : Item(verb
='Adding')
1477 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1478 expected_status
.add({
1479 "A/B_COPY_1" : Item(status
=' ', wc_rev
=2),
1480 "A/B_COPY_1/lambda" : Item(status
=' ', wc_rev
=2),
1481 "A/B_COPY_1/E" : Item(status
=' ', wc_rev
=2),
1482 "A/B_COPY_1/E/alpha" : Item(status
=' ', wc_rev
=2),
1483 "A/B_COPY_1/E/beta" : Item(status
=' ', wc_rev
=2),
1484 "A/B_COPY_1/F" : Item(status
=' ', wc_rev
=2),
1485 "A/B_COPY_2" : Item(status
=' ', wc_rev
=2),
1486 "A/B_COPY_2/lambda" : Item(status
=' ', wc_rev
=2),
1487 "A/B_COPY_2/E" : Item(status
=' ', wc_rev
=2),
1488 "A/B_COPY_2/E/alpha" : Item(status
=' ', wc_rev
=2),
1489 "A/B_COPY_2/E/beta" : Item(status
=' ', wc_rev
=2),
1490 "A/B_COPY_2/F" : Item(status
=' ', wc_rev
=2),
1493 svntest
.actions
.run_and_verify_commit(wc_dir
,
1497 None, None, None, None,
1500 # Make some changes under A/B
1502 # r3 - modify and commit A/B/E/beta
1503 svntest
.main
.file_write(beta_path
, "New content")
1504 expected_output
= svntest
.wc
.State(wc_dir
,
1505 {'A/B/E/beta' : Item(verb
='Sending')})
1506 expected_status
.tweak('A/B/E/beta', wc_rev
=3)
1507 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
1508 expected_status
, None, None, None,
1511 # r4 - modify and commit A/B/E/alpha
1512 svntest
.main
.file_write(alpha_path
, "New content")
1513 expected_output
= svntest
.wc
.State(wc_dir
,
1514 {'A/B/E/alpha' : Item(verb
='Sending')})
1515 expected_status
.tweak('A/B/E/alpha', wc_rev
=4)
1516 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
1517 expected_status
, None, None, None,
1520 # Merge r2:4 into A/B_COPY_1
1521 short_B_COPY_1_path
= shorten_path_kludge(B_COPY_1_path
)
1522 expected_output
= svntest
.wc
.State(short_B_COPY_1_path
, {
1523 'E/alpha' : Item(status
='U '),
1524 'E/beta' : Item(status
='U '),
1526 expected_merge_status
= svntest
.wc
.State(short_B_COPY_1_path
, {
1527 '' : Item(status
=' M', wc_rev
=2),
1528 'lambda' : Item(status
=' ', wc_rev
=2),
1529 'E' : Item(status
=' ', wc_rev
=2),
1530 'E/alpha' : Item(status
='M ', wc_rev
=2),
1531 'E/beta' : Item(status
='M ', wc_rev
=2),
1532 'F' : Item(status
=' ', wc_rev
=2),
1534 expected_merge_disk
= svntest
.wc
.State('', {
1535 '' : Item(props
={SVN_PROP_MERGE_INFO
: '/A/B:3-4'}),
1536 'lambda' : Item("This is the file 'lambda'.\n"),
1538 'E/alpha' : Item("New content"),
1539 'E/beta' : Item("New content"),
1542 expected_skip
= svntest
.wc
.State(short_B_COPY_1_path
, { })
1543 saved_cwd
= os
.getcwd()
1545 os
.chdir(svntest
.main
.work_dir
)
1546 svntest
.actions
.run_and_verify_merge(short_B_COPY_1_path
, '2', '4',
1550 expected_merge_disk
,
1551 expected_merge_status
,
1553 None, None, None, None,
1558 # r5 - Commit the merge into A/B_COPY_1/E
1559 expected_output
= svntest
.wc
.State(
1561 {'A/B_COPY_1' : Item(verb
='Sending'),
1562 'A/B_COPY_1/E/alpha' : Item(verb
='Sending'),
1563 'A/B_COPY_1/E/beta' : Item(verb
='Sending'),
1565 expected_status
.tweak('A/B_COPY_1', wc_rev
=5)
1566 expected_status
.tweak('A/B_COPY_1/E/alpha', wc_rev
=5)
1567 expected_status
.tweak('A/B_COPY_1/E/beta', wc_rev
=5)
1568 expected_status
.tweak('A/B_COPY_1/lambda', wc_rev
=2)
1569 svntest
.actions
.run_and_verify_commit(wc_dir
, expected_output
,
1570 expected_status
, None, None, None,
1573 # Merge r2:4 into A/B_COPY_2/E
1574 short_E_COPY_2_path
= shorten_path_kludge(E_COPY_2_path
)
1575 expected_output
= svntest
.wc
.State(short_E_COPY_2_path
, {
1576 'alpha' : Item(status
='U '),
1577 'beta' : Item(status
='U '),
1579 expected_merge_status
= svntest
.wc
.State(short_E_COPY_2_path
, {
1580 '' : Item(status
=' M', wc_rev
=2),
1581 'alpha' : Item(status
='M ', wc_rev
=2),
1582 'beta' : Item(status
='M ', wc_rev
=2),
1584 expected_merge_disk
= svntest
.wc
.State('', {
1585 '' : Item(props
={SVN_PROP_MERGE_INFO
: '/A/B/E:3-4'}),
1586 'alpha' : Item("New content"),
1587 'beta' : Item("New content"),
1589 expected_skip
= svntest
.wc
.State(short_E_COPY_2_path
, { })
1590 saved_cwd
= os
.getcwd()
1592 os
.chdir(svntest
.main
.work_dir
)
1593 svntest
.actions
.run_and_verify_merge(short_E_COPY_2_path
, '2', '4',
1597 expected_merge_disk
,
1598 expected_merge_status
,
1600 None, None, None, None,
1605 # Switch A/B_COPY_2 to URL of A/B_COPY_1. The local mergeinfo for r1,3-4
1606 # on A/B_COPY_2/E is identical to the mergeinfo added to A/B_COPY_2 as a
1607 # result of the switch, but we leave the former in place.
1609 # Setup expected results of switch.
1610 expected_output
= svntest
.wc
.State(sbox
.wc_dir
, {
1611 "A/B_COPY_2" : Item(status
=' U'),
1612 "A/B_COPY_2/E/alpha" : Item(status
='G '),
1613 "A/B_COPY_2/E/beta" : Item(status
='G '),
1616 expected_disk
= svntest
.main
.greek_state
.copy()
1617 expected_disk
.tweak("A/B/E/alpha", contents
="New content")
1618 expected_disk
.tweak("A/B/E/beta", contents
="New content")
1620 "A/B_COPY_1" : Item(props
={SVN_PROP_MERGE_INFO
: '/A/B:3-4'}),
1621 "A/B_COPY_1/E" : Item(),
1622 "A/B_COPY_1/F" : Item(),
1623 "A/B_COPY_1/lambda" : Item("This is the file 'lambda'.\n"),
1624 "A/B_COPY_1/E/alpha" : Item("New content"),
1625 "A/B_COPY_1/E/beta" : Item("New content"),
1626 "A/B_COPY_2" : Item(props
={SVN_PROP_MERGE_INFO
: '/A/B:3-4'}),
1627 "A/B_COPY_2/E" : Item(props
={SVN_PROP_MERGE_INFO
: '/A/B/E:3-4'}),
1628 "A/B_COPY_2/F" : Item(),
1629 "A/B_COPY_2/lambda" : Item("This is the file 'lambda'.\n"),
1630 "A/B_COPY_2/E/alpha" : Item("New content"),
1631 "A/B_COPY_2/E/beta" : Item("New content"),
1633 expected_status
= svntest
.actions
.get_virginal_state(sbox
.wc_dir
, 1)
1634 expected_status
.tweak("A/B/E/beta", wc_rev
=3)
1635 expected_status
.tweak("A/B/E/alpha", wc_rev
=4)
1636 expected_status
.add({
1637 "A/B_COPY_1" : Item(status
=' ', wc_rev
=5),
1638 "A/B_COPY_1/E" : Item(status
=' ', wc_rev
=2),
1639 "A/B_COPY_1/F" : Item(status
=' ', wc_rev
=2),
1640 "A/B_COPY_1/lambda" : Item(status
=' ', wc_rev
=2),
1641 "A/B_COPY_1/E/alpha" : Item(status
=' ', wc_rev
=5),
1642 "A/B_COPY_1/E/beta" : Item(status
=' ', wc_rev
=5),
1643 "A/B_COPY_2" : Item(status
=' ', wc_rev
=5, switched
='S'),
1644 "A/B_COPY_2/E" : Item(status
=' M', wc_rev
=5),
1645 "A/B_COPY_2/F" : Item(status
=' ', wc_rev
=5),
1646 "A/B_COPY_2/lambda" : Item(status
=' ', wc_rev
=5),
1647 "A/B_COPY_2/E/alpha" : Item(status
=' ', wc_rev
=5),
1648 "A/B_COPY_2/E/beta" : Item(status
=' ', wc_rev
=5),
1651 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
,
1653 sbox
.repo_url
+ "/A/B_COPY_1",
1657 None, None, None, None, None, 1)
1659 # Now check a switch which reverses and earlier switch and leaves
1660 # a path in an unswitched state.
1662 # Switch A/B_COPY_1/lambda to iota. Use propset to give A/B_COPY/lambda
1663 # the mergeinfo '/A/B/lambda:1,3-4'. Then switch A/B_COPY_1/lambda back
1664 # to A/B_COPY_1/lambda. The local mergeinfo for r1,3-4 should remain on
1665 # A/B_COPY_1/lambda.
1666 expected_output
= svntest
.wc
.State(sbox
.wc_dir
, {
1667 "A/B_COPY_1/lambda" : Item(status
='U '),
1669 expected_disk
.tweak("A/B_COPY_1/lambda",
1670 contents
="This is the file 'iota'.\n")
1671 expected_status
.tweak("A/B_COPY_1/lambda", wc_rev
=5, switched
='S')
1672 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
,
1674 sbox
.repo_url
+ "/iota",
1678 None, None, None, None, None, 1)
1680 svntest
.actions
.run_and_verify_svn(None,
1681 ["property '" + SVN_PROP_MERGE_INFO
+
1682 "' set on '" + lambda_path
+ "'" +
1683 "\n"], [], 'ps', SVN_PROP_MERGE_INFO
,
1684 '/A/B/lambda:3-4', lambda_path
)
1686 expected_output
= svntest
.wc
.State(sbox
.wc_dir
, {
1687 "A/B_COPY_1/lambda" : Item(status
='U '),
1689 expected_disk
.tweak("A/B_COPY_1/lambda",
1690 contents
="This is the file 'lambda'.\n",
1691 props
={SVN_PROP_MERGE_INFO
: '/A/B/lambda:3-4'})
1692 expected_status
.tweak("A/B_COPY_1/lambda", switched
=None, status
=' M')
1693 svntest
.actions
.run_and_verify_switch(sbox
.wc_dir
,
1695 sbox
.repo_url
+ "/A/B_COPY_1/lambda",
1699 None, None, None, None, None, 1)
1701 #----------------------------------------------------------------------
1703 def switch_with_depth(sbox
):
1704 "basic tests to verify switch along with depth"
1708 # Form some paths and URLs required
1709 wc_dir
= sbox
.wc_dir
1710 repo_url
= sbox
.repo_url
1711 AD_url
= repo_url
+ '/A/D'
1712 AB_url
= repo_url
+ '/A/B'
1713 AB_path
= os
.path
.join(wc_dir
, 'A', 'B')
1715 # Set up expected results of '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)
1719 expected_status
.tweak('A/B', switched
='S')
1720 expected_status
.tweak('A/B/lambda', switched
='S')
1721 expected_status
.tweak('A/B/E', switched
='S')
1722 expected_status
.tweak('A/B/F', switched
='S')
1724 # Do 'switch --depth=empty' and check the results in three ways.
1725 svntest
.actions
.run_and_verify_switch(wc_dir
, AB_path
, AD_url
,
1728 expected_status
, None,
1729 None, None, None, None, 0,
1732 # Set up expected results for reverting 'switch --depth=empty'
1733 expected_output
= svntest
.wc
.State(wc_dir
, {})
1734 expected_disk
= svntest
.main
.greek_state
.copy()
1735 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1737 svntest
.actions
.run_and_verify_switch(wc_dir
, AB_path
, AB_url
,
1740 expected_status
, None,
1741 None, None, None, None, 0,
1744 # Set up expected results of 'switch --depth=files'
1745 expected_output
= svntest
.wc
.State(wc_dir
, {
1746 'A/B/lambda' : Item(status
='D '),
1747 'A/B/gamma' : Item(status
='A '),
1749 expected_disk
= svntest
.main
.greek_state
.copy()
1750 expected_disk
.remove('A/B/lambda')
1752 'A/B/gamma' : Item("This is the file 'gamma'.\n")
1754 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1755 expected_status
.remove('A/B/lambda')
1756 expected_status
.add({
1757 'A/B/gamma' : Item(status
=' ', wc_rev
=1)
1759 expected_status
.tweak('A/B', switched
='S')
1760 expected_status
.tweak('A/B/E', switched
='S')
1761 expected_status
.tweak('A/B/F', switched
='S')
1763 # Do 'switch --depth=files' and check the results in three ways.
1764 svntest
.actions
.run_and_verify_switch(wc_dir
, AB_path
, AD_url
,
1767 expected_status
, None,
1768 None, None, None, None, 0,
1771 # Set up expected results for reverting 'switch --depth=files'
1772 expected_output
= svntest
.wc
.State(wc_dir
, {
1773 'A/B/gamma' : Item(status
='D '),
1774 'A/B/lambda' : Item(status
='A '),
1776 expected_disk
= svntest
.main
.greek_state
.copy()
1777 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1779 svntest
.actions
.run_and_verify_switch(wc_dir
, AB_path
, AB_url
,
1782 expected_status
, None,
1783 None, None, None, None, 0,
1786 # Putting the depth=immediates stuff in a subroutine, because we're
1787 # going to run it at least twice.
1789 # Set up expected results of 'switch --depth=immediates'
1790 expected_output
= svntest
.wc
.State(wc_dir
, {
1791 'A/B/lambda' : Item(status
='D '),
1792 'A/B/E' : Item(status
='D '),
1793 'A/B/F' : Item(status
='D '),
1794 'A/B/gamma' : Item(status
='A '),
1795 'A/B/G' : Item(status
='A '),
1796 'A/B/H' : Item(status
='A '),
1798 expected_disk
= svntest
.main
.greek_state
.copy()
1799 expected_disk
.remove('A/B/lambda', 'A/B/E/beta', 'A/B/E/alpha',
1802 'A/B/gamma' : Item("This is the file 'gamma'.\n"),
1806 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1807 expected_status
.remove('A/B/lambda', 'A/B/E/beta', 'A/B/E/alpha',
1809 expected_status
.add({
1810 'A/B/gamma' : Item(status
=' ', wc_rev
=1),
1811 'A/B/G' : Item(status
=' ', wc_rev
=1),
1812 'A/B/H' : Item(status
=' ', wc_rev
=1)
1814 expected_status
.tweak('A/B', switched
='S')
1816 # Do 'switch --depth=immediates' and check the results in three ways.
1817 svntest
.actions
.run_and_verify_switch(wc_dir
, AB_path
, AD_url
,
1820 expected_status
, None,
1821 None, None, None, None, 0,
1822 '--depth', 'immediates')
1826 # Set up expected results for reverting 'switch --depth=immediates'.
1827 # (Reverting with default [infinite] depth, so that the result is a
1828 # standard Greek Tree working copy again.)
1829 expected_output
= svntest
.wc
.State(wc_dir
, {
1830 'A/B/gamma' : Item(status
='D '),
1831 'A/B/G' : Item(status
='D '),
1832 'A/B/H' : Item(status
='D '),
1833 'A/B/lambda' : Item(status
='A '),
1834 'A/B/E' : Item(status
='A '),
1835 'A/B/E/alpha' : Item(status
='A '),
1836 'A/B/E/beta' : Item(status
='A '),
1837 'A/B/F' : Item(status
='A '),
1839 expected_disk
= svntest
.main
.greek_state
.copy()
1840 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1841 svntest
.actions
.run_and_verify_switch(wc_dir
, AB_path
, AB_url
,
1844 expected_status
, None,
1845 None, None, None, None, 0)
1847 # Okay, repeat 'switch --depth=immediates'. (Afterwards we'll
1848 # 'switch --depth=infinity', to test going all the way.)
1851 # Set up expected results of 'switch --depth=infinity'
1852 expected_output
= svntest
.wc
.State(wc_dir
, {
1853 'A/B/gamma' : Item(status
='D '),
1854 'A/B/G' : Item(status
='D '),
1855 'A/B/H' : Item(status
='D '),
1856 'A/B/lambda' : Item(status
='A '),
1857 'A/B/E' : Item(status
='A '),
1858 'A/B/E/alpha' : Item(status
='A '),
1859 'A/B/E/beta' : Item(status
='A '),
1860 'A/B/F' : Item(status
='A '),
1862 expected_disk
= svntest
.main
.greek_state
.copy()
1863 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1865 # Do the 'switch --depth=infinity' and check the results in three ways.
1866 svntest
.actions
.run_and_verify_switch(wc_dir
, AB_path
, AB_url
,
1869 expected_status
, None,
1870 None, None, None, None, 0,
1871 '--depth', 'infinity')
1873 #----------------------------------------------------------------------
1875 def switch_to_dir_with_peg_rev(sbox
):
1876 "switch to dir@peg where dir doesn't exist in HEAD"
1879 wc_dir
= sbox
.wc_dir
1880 repo_url
= sbox
.repo_url
1882 # prepare two dirs X and Y in rev. 2
1883 X_path
= os
.path
.join(wc_dir
, 'X')
1884 Y_path
= os
.path
.join(wc_dir
, 'Y')
1885 svntest
.main
.run_svn(None, 'mkdir', X_path
, Y_path
)
1886 svntest
.main
.run_svn(None, 'ci',
1887 '-m', 'log message',
1890 # change tau in rev. 3
1891 ADG_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
1892 tau_path
= os
.path
.join(ADG_path
, 'tau')
1893 svntest
.main
.file_append(tau_path
, "new line\n")
1894 svntest
.main
.run_svn(None, 'ci',
1895 '-m', 'log message',
1898 # delete A/D/G in rev. 4
1899 svntest
.main
.run_svn(None, 'up', wc_dir
)
1900 svntest
.main
.run_svn(None, 'rm', ADG_path
)
1901 svntest
.main
.run_svn(None, 'ci',
1902 '-m', 'log message',
1905 # Test 1: switch X to A/D/G@2
1906 ADG_url
= repo_url
+ '/A/D/G'
1907 expected_output
= svntest
.wc
.State(wc_dir
, {
1908 'X/pi' : Item(status
='A '),
1909 'X/rho' : Item(status
='A '),
1910 'X/tau' : Item(status
='A '),
1912 expected_disk
= svntest
.main
.greek_state
.copy()
1915 'X/pi' : Item("This is the file 'pi'.\n"),
1916 'X/rho' : Item("This is the file 'rho'.\n"),
1917 'X/tau' : Item("This is the file 'tau'.\n"),
1920 expected_disk
.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1921 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 3)
1922 expected_status
.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1923 expected_status
.add({
1924 'X' : Item(status
=' ', wc_rev
=2, switched
='S'),
1925 'X/pi' : Item(status
=' ', wc_rev
=2),
1926 'X/rho' : Item(status
=' ', wc_rev
=2),
1927 'X/tau' : Item(status
=' ', wc_rev
=2),
1928 'Y' : Item(status
=' ', wc_rev
=3)
1931 # Do the switch to rev. 2 of /A/D/G@3.
1932 svntest
.actions
.run_and_verify_switch(wc_dir
, X_path
, ADG_url
+ '@3',
1935 expected_status
, None,
1936 None, None, None, None, 0,
1939 def switch_urls_with_spaces(sbox
):
1940 "switch file and dir to url containing spaces"
1943 wc_dir
= sbox
.wc_dir
1944 repo_url
= sbox
.repo_url
1946 # add file and directory with spaces in their names.
1947 XYZ_path
= os
.path
.join(wc_dir
, 'X Y Z')
1948 ABC_path
= os
.path
.join(wc_dir
, 'A B C')
1949 svntest
.main
.run_svn(None, 'mkdir', XYZ_path
, ABC_path
)
1951 tpm_path
= os
.path
.join(wc_dir
, 'tau pau mau')
1952 bbb_path
= os
.path
.join(wc_dir
, 'bar baz bal')
1953 svntest
.main
.file_write(tpm_path
, "This is the file 'tau pau mau'.\n")
1954 svntest
.main
.file_write(bbb_path
, "This is the file 'bar baz bal'.\n")
1955 svntest
.main
.run_svn(None, 'add', tpm_path
, bbb_path
)
1957 svntest
.main
.run_svn(None, 'ci', '-m', 'log message', wc_dir
)
1959 # Test 1: switch directory 'A B C' to url 'X Y Z'
1960 XYZ_url
= repo_url
+ '/X Y Z'
1961 expected_output
= svntest
.wc
.State(wc_dir
, {
1963 expected_disk
= svntest
.main
.greek_state
.copy()
1967 'tau pau mau' : Item("This is the file 'tau pau mau'.\n"),
1968 'bar baz bal' : Item("This is the file 'bar baz bal'.\n"),
1970 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1971 expected_status
.add({
1972 'X Y Z' : Item(status
=' ', wc_rev
=2),
1973 'A B C' : Item(status
=' ', wc_rev
=2, switched
='S'),
1974 'tau pau mau' : Item(status
=' ', wc_rev
=2),
1975 'bar baz bal' : Item(status
=' ', wc_rev
=2),
1978 svntest
.actions
.run_and_verify_switch(wc_dir
, ABC_path
, XYZ_url
,
1983 # Test 2: switch file 'bar baz bal' to 'tau pau mau'
1984 tpm_url
= repo_url
+ '/tau pau mau'
1985 expected_output
= svntest
.wc
.State(wc_dir
, {
1986 'bar baz bal' : Item(status
='U '),
1988 expected_disk
= svntest
.main
.greek_state
.copy()
1992 'tau pau mau' : Item("This is the file 'tau pau mau'.\n"),
1993 'bar baz bal' : Item("This is the file 'tau pau mau'.\n"),
1995 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1996 expected_status
.add({
1997 'X Y Z' : Item(status
=' ', wc_rev
=2),
1998 'A B C' : Item(status
=' ', wc_rev
=2, switched
='S'),
1999 'tau pau mau' : Item(status
=' ', wc_rev
=2),
2000 'bar baz bal' : Item(status
=' ', wc_rev
=2, switched
='S'),
2003 svntest
.actions
.run_and_verify_switch(wc_dir
, bbb_path
, tpm_url
,
2008 def switch_to_dir_with_peg_rev2(sbox
):
2009 "switch to old rev of now renamed branch"
2012 wc_dir
= sbox
.wc_dir
2013 repo_url
= sbox
.repo_url
2015 # prepare dir X in rev. 2
2016 X_path
= os
.path
.join(wc_dir
, 'X')
2017 svntest
.main
.run_svn(None, 'mkdir', X_path
)
2018 svntest
.main
.run_svn(None, 'ci',
2019 '-m', 'log message',
2022 # make a change in ADG in rev. 3
2023 tau_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G', 'tau')
2024 svntest
.main
.file_append(tau_path
, "extra line\n")
2025 svntest
.main
.run_svn(None, 'ci', '-m', 'log message', wc_dir
)
2027 # Rename ADG to ADY in rev 4
2028 svntest
.main
.run_svn(None, 'up', wc_dir
)
2029 ADG_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
2030 ADY_path
= os
.path
.join(wc_dir
, 'A', 'D', 'Y')
2031 svntest
.main
.run_svn(None, 'mv', ADG_path
, ADY_path
)
2032 svntest
.main
.run_svn(None, 'ci',
2033 '-m', 'log message',
2036 # Test switch X to rev 2 of A/D/Y@HEAD
2037 ADY_url
= sbox
.repo_url
+ '/A/D/Y'
2038 expected_output
= svntest
.wc
.State(wc_dir
, {
2039 'X/pi' : Item(status
='A '),
2040 'X/rho' : Item(status
='A '),
2041 'X/tau' : Item(status
='A '),
2043 expected_disk
= svntest
.main
.greek_state
.copy()
2046 'X/pi' : Item("This is the file 'pi'.\n"),
2047 'X/rho' : Item("This is the file 'rho'.\n"),
2048 'X/tau' : Item("This is the file 'tau'.\n"),
2050 'A/D/Y/pi' : Item("This is the file 'pi'.\n"),
2051 'A/D/Y/rho' : Item("This is the file 'rho'.\n"),
2052 'A/D/Y/tau' : Item("This is the file 'tau'.\nextra line\n"),
2054 expected_disk
.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2056 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 3)
2057 expected_status
.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2058 expected_status
.add({
2059 'X' : Item(status
=' ', wc_rev
=2, switched
='S'),
2060 'X/pi' : Item(status
=' ', wc_rev
=2),
2061 'X/rho' : Item(status
=' ', wc_rev
=2),
2062 'X/tau' : Item(status
=' ', wc_rev
=2),
2063 'A/D/Y' : Item(status
=' ', wc_rev
=4),
2064 'A/D/Y/pi' : Item(status
=' ', wc_rev
=4),
2065 'A/D/Y/rho' : Item(status
=' ', wc_rev
=4),
2066 'A/D/Y/tau' : Item(status
=' ', wc_rev
=4),
2069 svntest
.actions
.run_and_verify_switch(wc_dir
, X_path
, ADY_url
+ '@HEAD',
2072 expected_status
, None,
2073 None, None, None, None, 0,
2076 def switch_to_root(sbox
):
2077 "switch a folder to the root of its repository"
2080 wc_dir
= sbox
.wc_dir
2081 repo_url
= sbox
.repo_url
2083 ADG_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
2085 # Test switch /A/D/G to /
2086 AD_url
= sbox
.repo_url
+ '/A/D'
2087 expected_output
= svntest
.wc
.State(wc_dir
, {
2088 'A/D/G/pi' : Item(status
='D '),
2089 'A/D/G/rho' : Item(status
='D '),
2090 'A/D/G/tau' : Item(status
='D '),
2091 'A/D/G/A' : Item(status
='A '),
2092 'A/D/G/A/B' : Item(status
='A '),
2093 'A/D/G/A/B/lambda' : Item(status
='A '),
2094 'A/D/G/A/B/E' : Item(status
='A '),
2095 'A/D/G/A/B/E/alpha' : Item(status
='A '),
2096 'A/D/G/A/B/E/beta' : Item(status
='A '),
2097 'A/D/G/A/B/F' : Item(status
='A '),
2098 'A/D/G/A/mu' : Item(status
='A '),
2099 'A/D/G/A/C' : Item(status
='A '),
2100 'A/D/G/A/D' : Item(status
='A '),
2101 'A/D/G/A/D/gamma' : Item(status
='A '),
2102 'A/D/G/A/D/G' : Item(status
='A '),
2103 'A/D/G/A/D/G/pi' : Item(status
='A '),
2104 'A/D/G/A/D/G/rho' : Item(status
='A '),
2105 'A/D/G/A/D/G/tau' : Item(status
='A '),
2106 'A/D/G/A/D/H' : Item(status
='A '),
2107 'A/D/G/A/D/H/chi' : Item(status
='A '),
2108 'A/D/G/A/D/H/omega' : Item(status
='A '),
2109 'A/D/G/A/D/H/psi' : Item(status
='A '),
2110 'A/D/G/iota' : Item(status
='A '),
2112 expected_disk
= svntest
.main
.greek_state
.copy()
2113 expected_disk
.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2114 expected_disk
.add_state('A/D/G', svntest
.main
.greek_state
.copy())
2116 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
2117 expected_status
.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2118 expected_status
.add_state('A/D/G',
2119 svntest
.actions
.get_virginal_state(wc_dir
, 1))
2120 expected_status
.tweak('A/D/G', switched
= 'S')
2121 svntest
.actions
.run_and_verify_switch(wc_dir
, ADG_path
, sbox
.repo_url
,
2126 ########################################################################
2129 # list all tests here, starting with None:
2132 commit_switched_things
,
2135 update_switched_things
,
2136 rev_update_switched_things
,
2138 relocate_deleted_missing_copied
,
2140 XFail(file_dir_file
),
2141 nonrecursive_switching
,
2142 failed_anchor_is_target
,
2143 bad_intermediate_urls
,
2145 commit_mods_below_switch
,
2146 relocate_beyond_repos_root
,
2147 refresh_read_only_attribute
,
2148 switch_change_repos_root
,
2149 XFail(relocate_and_propset
, svntest
.main
.is_ra_type_dav
),
2151 forced_switch_failures
,
2152 switch_scheduled_add
,
2153 mergeinfo_switch_elision
,
2154 switch_with_obstructing_local_adds
,
2156 switch_to_dir_with_peg_rev
,
2157 switch_urls_with_spaces
,
2158 switch_to_dir_with_peg_rev2
,
2162 if __name__
== '__main__':
2163 svntest
.main
.run_tests(test_list
)