In the command-line client, forbid
[svn.git] / subversion / tests / cmdline / switch_tests.py
blob2347b2e07c56f12f5afaabe1f778aa85e8513984
1 #!/usr/bin/env python
3 # switch_tests.py: testing `svn switch'.
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-2004 CollabNet. All rights reserved.
11 # This software is licensed as described in the file COPYING, which
12 # you should have received as part of this distribution. The terms
13 # are also available at http://subversion.tigris.org/license-1.html.
14 # If newer versions of this license are posted there, you may use a
15 # newer version instead, at your option.
17 ######################################################################
19 # General modules
20 import shutil, re, os
22 # Our testing module
23 import svntest
25 # (abbreviation)
26 Skip = svntest.testcase.Skip
27 XFail = svntest.testcase.XFail
28 Item = svntest.wc.StateItem
30 from svntest.main import SVN_PROP_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.
39 ###
40 ### gjs says: we have 'svn info' now
42 def get_routine_status_state(wc_dir):
43 """get the routine status list for WC_DIR at the completion of an
44 initial call to do_routine_switching()"""
46 # Construct some paths for convenience
47 ADH_path = os.path.join(wc_dir, 'A', 'D', 'H')
48 chi_path = os.path.join(ADH_path, 'chi')
49 omega_path = os.path.join(ADH_path, 'omega')
50 psi_path = os.path.join(ADH_path, 'psi')
51 pi_path = os.path.join(ADH_path, 'pi')
52 tau_path = os.path.join(ADH_path, 'tau')
53 rho_path = os.path.join(ADH_path, 'rho')
55 # Now generate a state
56 state = svntest.actions.get_virginal_state(wc_dir, 1)
57 state.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda')
58 state.add({
59 'A/B/pi' : Item(status=' ', wc_rev=1),
60 'A/B/tau' : Item(status=' ', wc_rev=1),
61 'A/B/rho' : Item(status=' ', wc_rev=1),
64 return state
66 #----------------------------------------------------------------------
68 def get_routine_disk_state(wc_dir):
69 """get the routine disk list for WC_DIR at the completion of an
70 initial call to do_routine_switching()"""
72 disk = svntest.main.greek_state.copy()
74 # iota has the same contents as gamma
75 disk.tweak('iota', contents=disk.desc['A/D/gamma'].contents)
77 # A/B/* no longer exist, but have been replaced by copies of A/D/G/*
78 disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda')
79 disk.add({
80 'A/B/pi' : Item("This is the file 'pi'.\n"),
81 'A/B/rho' : Item("This is the file 'rho'.\n"),
82 'A/B/tau' : Item("This is the file 'tau'.\n"),
85 return disk
87 #----------------------------------------------------------------------
89 def do_routine_switching(wc_dir, repo_url, verify):
90 """perform some routine switching of the working copy WC_DIR for
91 other tests to use. If VERIFY, then do a full verification of the
92 switching, else don't bother."""
94 ### Switch the file `iota' to `A/D/gamma'.
96 # Construct some paths for convenience
97 iota_path = os.path.join(wc_dir, 'iota')
98 gamma_url = repo_url + '/A/D/gamma'
100 if verify:
101 # Create expected output tree
102 expected_output = svntest.wc.State(wc_dir, {
103 'iota' : Item(status='U '),
106 # Create expected disk tree (iota will have gamma's contents)
107 expected_disk = svntest.main.greek_state.copy()
108 expected_disk.tweak('iota',
109 contents=expected_disk.desc['A/D/gamma'].contents)
111 # Create expected status tree
112 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
113 expected_status.tweak('iota', switched='S')
115 # Do the switch and check the results in three ways.
116 svntest.actions.run_and_verify_switch(wc_dir, iota_path, gamma_url,
117 expected_output,
118 expected_disk,
119 expected_status)
120 else:
121 svntest.main.run_svn(None, 'switch',
122 gamma_url, iota_path)
124 ### Switch the directory `A/B' to `A/D/G'.
126 # Construct some paths for convenience
127 AB_path = os.path.join(wc_dir, 'A', 'B')
128 ADG_url = repo_url + '/A/D/G'
130 if verify:
131 # Create expected output tree
132 expected_output = svntest.wc.State(wc_dir, {
133 'A/B/E' : Item(status='D '),
134 'A/B/F' : Item(status='D '),
135 'A/B/lambda' : Item(status='D '),
136 'A/B/pi' : Item(status='A '),
137 'A/B/tau' : Item(status='A '),
138 'A/B/rho' : Item(status='A '),
141 # Create expected disk tree (iota will have gamma's contents,
142 # A/B/* will look like A/D/G/*)
143 expected_disk = get_routine_disk_state(wc_dir)
145 # Create expected status
146 expected_status = get_routine_status_state(wc_dir)
147 expected_status.tweak('iota', 'A/B', switched='S')
149 # Do the switch and check the results in three ways.
150 svntest.actions.run_and_verify_switch(wc_dir, AB_path, ADG_url,
151 expected_output,
152 expected_disk,
153 expected_status)
154 else:
155 svntest.main.run_svn(None,
156 'switch', ADG_url, AB_path)
159 #----------------------------------------------------------------------
161 def commit_routine_switching(wc_dir, verify):
162 "Commit some stuff in a routinely-switched working copy."
164 # Make some local mods
165 iota_path = os.path.join(wc_dir, 'iota')
166 Bpi_path = os.path.join(wc_dir, 'A', 'B', 'pi')
167 Gpi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi')
168 Z_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z')
169 zeta_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z', 'zeta')
171 svntest.main.file_append(iota_path, "apple")
172 svntest.main.file_append(Bpi_path, "melon")
173 svntest.main.file_append(Gpi_path, "banana")
174 os.mkdir(Z_path)
175 svntest.main.file_append(zeta_path, "This is the file 'zeta'.\n")
176 svntest.main.run_svn(None, 'add', Z_path)
178 # Try to commit. We expect this to fail because, if all the
179 # switching went as expected, A/B/pi and A/D/G/pi point to the
180 # same URL. We don't allow this.
181 svntest.actions.run_and_verify_commit(
182 wc_dir, None, None,
183 "svn: Cannot commit both .* as they refer to the same URL$",
184 None, None, None, None,
185 wc_dir)
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
210 if verify:
211 svntest.actions.run_and_verify_commit(wc_dir,
212 expected_output,
213 expected_status,
214 None, None, None, None, None,
215 wc_dir)
216 else:
217 svntest.main.run_svn(None,
218 'ci', '-m', 'log msg', wc_dir)
221 ######################################################################
222 # Tests
225 #----------------------------------------------------------------------
227 def routine_switching(sbox):
228 "test some basic switching operations"
230 sbox.build()
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"
241 sbox.build()
242 wc_dir = sbox.wc_dir
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"
256 sbox.build()
257 wc_dir = sbox.wc_dir
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")
297 expected_disk.add({
298 'A/B/Z' : Item(),
299 'A/B/Z/zeta' : Item(contents="This is the file 'zeta'.\n"),
300 'A/D/G/Z' : Item(),
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,
316 expected_output,
317 expected_disk,
318 expected_status)
320 #----------------------------------------------------------------------
322 def full_rev_update(sbox):
323 "reverse update wc that contains switched things"
325 sbox.build()
326 wc_dir = sbox.wc_dir
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,
363 expected_output,
364 expected_disk,
365 expected_status,
366 None, None, None,
367 None, None, 1,
368 '-r', '1', wc_dir)
370 #----------------------------------------------------------------------
372 def update_switched_things(sbox):
373 "update switched wc things to HEAD"
375 sbox.build()
376 wc_dir = sbox.wc_dir
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")
405 expected_disk.add({
406 'A/B/Z' : Item(),
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',
414 wc_rev=2)
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,
421 expected_output,
422 expected_disk,
423 expected_status,
424 None, None, None,
425 None, None, 0,
426 B_path,
427 iota_path)
430 #----------------------------------------------------------------------
432 def rev_update_switched_things(sbox):
433 "reverse update switched wc things to an older rev"
435 sbox.build()
436 wc_dir = sbox.wc_dir
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")
462 expected_disk.add({
463 'A/D/G/Z' : Item(),
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',
472 wc_rev=1)
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,
479 expected_output,
480 expected_disk,
481 expected_status,
482 None, None, None,
483 None, None, 1,
484 '-r', '1',
485 B_path,
486 iota_path)
489 #----------------------------------------------------------------------
491 def log_switched_file(sbox):
492 "show logs for a switched file"
494 sbox.build()
495 wc_dir = sbox.wc_dir
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,
504 'ci', '-m',
505 'set prop on switched iota',
506 iota_path)
508 # log switched file 'iota'
509 output, error = svntest.main.run_svn(None, 'log', iota_path)
510 for line in output:
511 if line.find("set prop on switched iota") != -1:
512 break
513 else:
514 raise svntest.Failure
516 #----------------------------------------------------------------------
518 def relocate_deleted_missing_copied(sbox):
519 "relocate with deleted, missing and copied entries"
520 sbox.build()
521 wc_dir = sbox.wc_dir
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,
532 expected_output,
533 expected_status,
534 None, None, None, None, None,
535 wc_dir)
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',
544 H_path, H2_path)
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)
554 # Relocate
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')
570 expected_disk.add({
571 'A/D/H2' : Item(),
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',
581 wc_rev='-')
582 svntest.actions.run_and_verify_update(wc_dir,
583 expected_output,
584 expected_disk,
585 expected_status)
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,
596 wc_dir)
599 #----------------------------------------------------------------------
601 def delete_subdir(sbox):
602 "switch that deletes a sub-directory"
603 sbox.build()
604 wc_dir = sbox.wc_dir
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,
632 expected_output,
633 expected_disk,
634 expected_status)
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"
641 sbox.build()
642 wc_dir = sbox.wc_dir
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"
660 sbox.build()
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,
688 'up', wc1_dir)
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, [],
699 'info', wc2_B_dir)
700 if out[1].find('/A/B') == -1:
701 print out[1]
702 raise svntest.Failure
704 out, err = svntest.actions.run_and_verify_svn(None, None, [],
705 'info', wc2_C_dir)
706 if out[1].find('/A/C') == -1:
707 print out[1]
708 raise svntest.Failure
710 out, err = svntest.actions.run_and_verify_svn(None, None, [],
711 'info', wc2_D_dir)
712 if out[1].find('/A/D') == -1:
713 print out[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.)
719 # mu: not switched
720 out, err = svntest.actions.run_and_verify_svn(None, None, [],
721 'info', wc2_mu_file)
722 if out[2].find('/branch/version1/mu') == -1:
723 print out[2]
724 raise svntest.Failure
725 # newfile: wrong URL
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:
729 print out[2]
730 raise svntest.Failure
733 #----------------------------------------------------------------------
734 def failed_anchor_is_target(sbox):
735 "anchor=target that fails due to local mods"
736 sbox.build()
737 wc_dir = sbox.wc_dir
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',
752 G_url, H_path)
753 if not err:
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)
776 for line in out:
777 if line.find('URL: ' + G_url) != -1:
778 break
779 else:
780 raise svntest.Failure
782 # Remove the now-unversioned psi, and repeat the switch. This
783 # should complete the switch.
784 os.remove(psi_path)
785 svntest.actions.run_and_verify_svn(None, None, [], 'switch',
786 G_url, H_path)
788 expected_status.tweak('A/D/H', status=' ') # remains switched
789 expected_status.add({ 'A/D/H/psi' : Item(status=' ',
790 switched=None,
791 wc_rev=2) })
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"
799 sbox.build()
800 wc_dir = sbox.wc_dir
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',
812 C_A_url, C_A_Z_url)
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',
821 C_url, wc_dir)
822 if not err:
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, [],
827 'info', A_path)
828 if out[1].find('/A/C/A') == -1:
829 raise svntest.Failure
833 #----------------------------------------------------------------------
834 # Regression test for issue #1825: failed switch may corrupt
835 # working copy
837 def obstructed_switch(sbox):
838 "obstructed switch"
839 sbox.build()
840 wc_dir = sbox.wc_dir
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,
859 wc_dir)
861 svntest.main.file_append(alpha_path, "hello")
862 out, err = svntest.main.run_svn(1,
863 'sw', E_url2, E_path)
864 for line in err:
865 if line.find("object of the same name already exists") != -1:
866 break
867 else:
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 #----------------------------------------------------------------------
879 # Issue 2353.
880 def commit_mods_below_switch(sbox):
881 "commit with mods below switch"
882 sbox.build()
883 wc_dir = sbox.wc_dir
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()
895 expected_disk.add({
896 'A/C/E' : Item(),
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"),
899 'A/C/F' : Item(),
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,
912 expected_output,
913 expected_disk,
914 expected_status)
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,
934 C_path, D_path)
936 def relocate_beyond_repos_root(sbox):
937 "relocate with prefixes longer than repo root"
938 sbox.build()
940 wc_dir = sbox.wc_dir
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
960 # repository root.
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
973 # (e.g. '+').
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 #----------------------------------------------------------------------
980 # Issue 2306.
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
985 # the test.
986 if os.name == 'posix':
987 if os.geteuid() == 0:
988 raise svntest.Skip
990 sbox.build()
991 wc_dir = sbox.wc_dir
993 # Create a branch.
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',
999 url, branch_url)
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,
1016 mu_path)
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
1024 # svn:needs-lock.
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,
1035 expected_output,
1036 expected_disk,
1037 expected_status)
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"
1049 sbox.build()
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,
1067 expected_err,
1068 'switch',
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.*",
1078 'switch',
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)
1085 # Issue 2578.
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)
1103 # checkout
1104 svntest.main.safe_rmtree(wc_dir, 1)
1105 svntest.actions.run_and_verify_svn(None,
1106 None, [],
1107 'checkout',
1108 repo_url, wc_dir)
1110 # Relocate
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,
1133 expected_output,
1134 expected_status,
1135 None, None, None, None, None,
1136 wc_dir)
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,
1146 None,
1147 None,
1148 "[Oo]ut.of.date",
1149 None, None,
1150 None, None,
1151 wc_dir)
1153 #----------------------------------------------------------------------
1155 def forced_switch(sbox):
1156 "forced switch tolerates obstructions to adds"
1157 sbox.build()
1159 # Dir obstruction
1160 G_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G')
1161 os.mkdir(G_path)
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')
1176 os.mkdir(I_path)
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()
1194 expected_disk.add({
1195 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
1196 "A/B/F/G" : Item(),
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"),
1201 "A/B/F/H" : Item(),
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"),
1205 "A/B/F/I" : Item(),
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,
1225 expected_output,
1226 expected_disk,
1227 expected_status, None,
1228 None, None, None, None, 0,
1229 '--force')
1231 #----------------------------------------------------------------------
1233 def forced_switch_failures(sbox):
1234 "forced switch fails with some types of obstuctions"
1235 sbox.build()
1237 # Add a directory to obstruct a file.
1238 pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'pi')
1239 os.mkdir(pi_path)
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",
1252 None, None, None,
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,
1262 'A', 'B', 'F'),
1263 sbox.repo_url + "/A/D/G",
1264 None, None, None,
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'],
1278 "mkdir", I_url,
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')
1283 os.mkdir(I_path)
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,
1294 'A', 'D', 'G'),
1295 sbox.repo_url + "/A/D/H",
1296 None, None, None,
1297 ".*Failed to add " + \
1298 "directory .*: a versioned " + \
1299 "directory of the same name " + \
1300 "already exists\n",
1301 None, None, None, None, 0, '--force')
1303 def switch_with_obstructing_local_adds(sbox):
1304 "switch tolerates WC adds"
1305 sbox.build()
1307 # Dir obstruction scheduled for addition without history.
1308 G_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G')
1309 os.mkdir(G_path)
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'),
1315 gamma_copy_path)
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')
1327 os.mkdir(I_path)
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,
1335 gamma_copy_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()
1351 expected_disk.add({
1352 "A/B/F/gamma" : Item("This is the file 'gamma'.\n"),
1353 "A/B/F/G" : Item(),
1354 "A/B/F/G/pi" : Item("\n".join(["<<<<<<< .mine",
1355 "This is the OBSTRUCTING file 'pi'.",
1356 "=======",
1357 "This is the file 'pi'.",
1358 ">>>>>>> .r1",
1359 ""])),
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"),
1363 "A/B/F/H" : Item(),
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"),
1367 "A/B/F/I" : Item(),
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,
1393 expected_output,
1394 expected_disk,
1395 expected_status,
1396 None,
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"
1404 sbox.build()
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, [],
1412 'add', file_path)
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
1428 # this function.
1429 def shorten_path_kludge(path):
1430 shorten_by = len(svntest.main.work_dir) + len(os.sep)
1431 return path[shorten_by:]
1433 sbox.build()
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(
1446 None,
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"],
1455 'copy',
1456 sbox.repo_url + "/A/B",
1457 B_COPY_1_path)
1459 svntest.actions.run_and_verify_svn(
1460 None,
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"],
1469 'copy',
1470 sbox.repo_url + "/A/B",
1471 B_COPY_2_path)
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,
1494 expected_output,
1495 expected_status,
1496 None,
1497 None, None, None, None,
1498 wc_dir)
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,
1509 None, None, wc_dir)
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,
1518 None, None, wc_dir)
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"),
1537 'E' : Item(),
1538 'E/alpha' : Item("New content"),
1539 'E/beta' : Item("New content"),
1540 'F' : Item(),
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',
1547 sbox.repo_url + \
1548 '/A/B',
1549 expected_output,
1550 expected_merge_disk,
1551 expected_merge_status,
1552 expected_skip,
1553 None, None, None, None,
1554 None, 1)
1556 os.chdir(saved_cwd)
1558 # r5 - Commit the merge into A/B_COPY_1/E
1559 expected_output = svntest.wc.State(
1560 wc_dir,
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,
1571 None, None, wc_dir)
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',
1594 sbox.repo_url + \
1595 '/A/B/E',
1596 expected_output,
1597 expected_merge_disk,
1598 expected_merge_status,
1599 expected_skip,
1600 None, None, None, None,
1601 None, 1)
1603 os.chdir(saved_cwd)
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")
1619 expected_disk.add({
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,
1652 B_COPY_2_path,
1653 sbox.repo_url + "/A/B_COPY_1",
1654 expected_output,
1655 expected_disk,
1656 expected_status,
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,
1673 lambda_path,
1674 sbox.repo_url + "/iota",
1675 expected_output,
1676 expected_disk,
1677 expected_status,
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,
1694 lambda_path,
1695 sbox.repo_url + "/A/B_COPY_1/lambda",
1696 expected_output,
1697 expected_disk,
1698 expected_status,
1699 None, None, None, None, None, 1)
1701 #----------------------------------------------------------------------
1703 def switch_with_depth(sbox):
1704 "basic tests to verify switch along with depth"
1706 sbox.build()
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,
1726 expected_output,
1727 expected_disk,
1728 expected_status, None,
1729 None, None, None, None, 0,
1730 '--depth', 'empty')
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,
1738 expected_output,
1739 expected_disk,
1740 expected_status, None,
1741 None, None, None, None, 0,
1742 '--depth', 'empty')
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')
1751 expected_disk.add({
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,
1765 expected_output,
1766 expected_disk,
1767 expected_status, None,
1768 None, None, None, None, 0,
1769 '--depth', 'files')
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,
1780 expected_output,
1781 expected_disk,
1782 expected_status, None,
1783 None, None, None, None, 0,
1784 '--depth', 'files')
1786 # Putting the depth=immediates stuff in a subroutine, because we're
1787 # going to run it at least twice.
1788 def sw_depth_imm():
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',
1800 'A/B/E', 'A/B/F')
1801 expected_disk.add({
1802 'A/B/gamma' : Item("This is the file 'gamma'.\n"),
1803 'A/B/G' : Item(),
1804 'A/B/H' : Item(),
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',
1808 'A/B/E', 'A/B/F')
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,
1818 expected_output,
1819 expected_disk,
1820 expected_status, None,
1821 None, None, None, None, 0,
1822 '--depth', 'immediates')
1824 sw_depth_imm()
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,
1842 expected_output,
1843 expected_disk,
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.)
1849 sw_depth_imm()
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,
1867 expected_output,
1868 expected_disk,
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"
1878 sbox.build()
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',
1888 wc_dir)
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',
1896 wc_dir)
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',
1903 wc_dir)
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()
1913 expected_disk.add({
1914 'X' : Item(),
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"),
1918 'Y' : Item(),
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',
1933 expected_output,
1934 expected_disk,
1935 expected_status, None,
1936 None, None, None, None, 0,
1937 '-r', '2')
1939 def switch_urls_with_spaces(sbox):
1940 "switch file and dir to url containing spaces"
1942 sbox.build()
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()
1964 expected_disk.add({
1965 'X Y Z' : Item(),
1966 'A B C' : Item(),
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,
1979 expected_output,
1980 expected_disk,
1981 expected_status)
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()
1989 expected_disk.add({
1990 'X Y Z' : Item(),
1991 'A B C' : Item(),
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,
2004 expected_output,
2005 expected_disk,
2006 expected_status)
2008 def switch_to_dir_with_peg_rev2(sbox):
2009 "switch to old rev of now renamed branch"
2011 sbox.build()
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',
2020 wc_dir)
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',
2034 wc_dir)
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()
2044 expected_disk.add({
2045 'X' : Item(),
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"),
2049 'A/D/Y' : Item(),
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',
2070 expected_output,
2071 expected_disk,
2072 expected_status, None,
2073 None, None, None, None, 0,
2074 '-r', '2')
2076 def switch_to_root(sbox):
2077 "switch a folder to the root of its repository"
2079 sbox.build()
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,
2122 expected_output,
2123 expected_disk,
2124 expected_status)
2126 ########################################################################
2127 # Run the tests
2129 # list all tests here, starting with None:
2130 test_list = [ None,
2131 routine_switching,
2132 commit_switched_things,
2133 full_update,
2134 full_rev_update,
2135 update_switched_things,
2136 rev_update_switched_things,
2137 log_switched_file,
2138 relocate_deleted_missing_copied,
2139 delete_subdir,
2140 XFail(file_dir_file),
2141 nonrecursive_switching,
2142 failed_anchor_is_target,
2143 bad_intermediate_urls,
2144 obstructed_switch,
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),
2150 forced_switch,
2151 forced_switch_failures,
2152 switch_scheduled_add,
2153 mergeinfo_switch_elision,
2154 switch_with_obstructing_local_adds,
2155 switch_with_depth,
2156 switch_to_dir_with_peg_rev,
2157 switch_urls_with_spaces,
2158 switch_to_dir_with_peg_rev2,
2159 switch_to_root,
2162 if __name__ == '__main__':
2163 svntest.main.run_tests(test_list)
2164 # NOTREACHED
2167 ### End of file.