3 # depth_tests.py: Testing that operations work as expected at
4 # various depths (depth-empty, depth-files,
5 # depth-immediates, depth-infinity).
7 # Subversion is a tool for revision control.
8 # See http://subversion.tigris.org for more information.
10 # ====================================================================
11 # Copyright (c) 2007 CollabNet. All rights reserved.
13 # This software is licensed as described in the file COPYING, which
14 # you should have received as part of this distribution. The terms
15 # are also available at http://subversion.tigris.org/license-1.html.
16 # If newer versions of this license are posted there, you may use a
17 # newer version instead, at your option.
19 ######################################################################
26 from svntest
import wc
29 Skip
= svntest
.testcase
.Skip
30 XFail
= svntest
.testcase
.XFail
33 # For errors setting up the depthy working copies.
34 class DepthSetupError(Exception):
35 def __init__ (self
, args
=None):
38 def set_up_depthy_working_copies(sbox
, empty
=False, files
=False,
39 immediates
=False, infinity
=False):
40 """Set up up to four working copies, at various depths. At least
41 one of depths EMPTY, FILES, IMMEDIATES, or INFINITY must be passed
42 as True. The corresponding working copy paths are returned in a
43 four-element tuple in that order, with element value of None for
44 working copies that were not created. If all args are False, raise
47 if not (infinity
or empty
or files
or immediates
):
48 raise DepthSetupError("At least one working copy depth must be passed.")
55 sbox
.build(create_wc
= False)
56 sbox
.add_test_path(sbox
.wc_dir
, True)
60 wc_empty
= sbox
.wc_dir
+ '-depth-empty'
61 sbox
.add_test_path(wc_empty
, True)
62 svntest
.actions
.run_and_verify_svn(
63 "Unexpected error from co --depth=empty",
64 svntest
.verify
.AnyOutput
, [],
65 "co", "--depth", "empty", sbox
.repo_url
, wc_empty
)
69 wc_files
= sbox
.wc_dir
+ '-depth-files'
70 sbox
.add_test_path(wc_files
, True)
71 svntest
.actions
.run_and_verify_svn(
72 "Unexpected error from co --depth=files",
73 svntest
.verify
.AnyOutput
, [],
74 "co", "--depth", "files", sbox
.repo_url
, wc_files
)
78 wc_immediates
= sbox
.wc_dir
+ '-depth-immediates'
79 sbox
.add_test_path(wc_immediates
, True)
80 svntest
.actions
.run_and_verify_svn(
81 "Unexpected error from co --depth=immediates",
82 svntest
.verify
.AnyOutput
, [],
83 "co", "--depth", "immediates",
84 sbox
.repo_url
, wc_immediates
)
86 return wc_empty
, wc_files
, wc_immediates
, wc
89 #----------------------------------------------------------------------
90 # Ensure that 'checkout --depth=empty' results in a depth-empty working copy.
91 def depth_empty_checkout(sbox
):
92 "depth-empty checkout"
94 wc_empty
, ign_a
, ign_b
, ign_c
= set_up_depthy_working_copies(sbox
, empty
=True)
96 if os
.path
.exists(os
.path
.join(wc_empty
, "iota")):
97 raise svntest
.Failure("depth-empty checkout created file 'iota'")
99 if os
.path
.exists(os
.path
.join(wc_empty
, "A")):
100 raise svntest
.Failure("depth-empty checkout created subdir 'A'")
102 svntest
.actions
.run_and_verify_svn(
103 "Expected depth empty for top of WC, got some other depth",
104 "Depth: empty|Path.+|URL.+|Repository.+|Revision.+|Node Kind.+|" \
105 "Schedule.+|Last.+|\n",
106 [], "info", wc_empty
)
109 # Helper for two test functions.
110 def depth_files_same_as_nonrecursive(sbox
, opt
):
111 """Run a depth-files or non-recursive checkout, depending on whether
112 passed '-N' or '--depth=files' for OPT. The two should get the same
113 result, hence this helper containing the common code between the
116 # This duplicates some code from set_up_depthy_working_copies(), but
117 # that's because it's abstracting out a different axis.
119 sbox
.build(create_wc
= False)
120 if os
.path
.exists(sbox
.wc_dir
):
121 svntest
.main
.safe_rmtree(sbox
.wc_dir
)
123 svntest
.actions
.run_and_verify_svn("Unexpected error during co %s" % opt
,
124 svntest
.verify
.AnyOutput
, [],
125 "co", opt
, sbox
.repo_url
, sbox
.wc_dir
)
127 # Should create a depth-files top directory, so both iota and A
128 # should exist, and A should be empty and depth-empty.
130 if not os
.path
.exists(os
.path
.join(sbox
.wc_dir
, "iota")):
131 raise svntest
.Failure("'checkout %s' failed to create file 'iota'" % opt
)
133 if os
.path
.exists(os
.path
.join(sbox
.wc_dir
, "A")):
134 raise svntest
.Failure("'checkout %s' unexpectedly created subdir 'A'" % opt
)
136 svntest
.actions
.run_and_verify_svn(
137 "Expected depth files for top of WC, got some other depth",
138 "Depth: files|Path.+|URL.+|Repository.+|Revision.+|Node Kind.+|" \
139 "Schedule.+|Last.+|\n", [], "info", sbox
.wc_dir
)
142 def depth_files_checkout(sbox
):
143 "depth-files checkout"
144 depth_files_same_as_nonrecursive(sbox
, "--depth=files")
147 def nonrecursive_checkout(sbox
):
148 "non-recursive checkout equals depth-files"
149 depth_files_same_as_nonrecursive(sbox
, "-N")
152 #----------------------------------------------------------------------
153 def depth_empty_update_bypass_single_file(sbox
):
154 "update depth-empty wc shouldn't receive file mod"
156 wc_empty
, ign_a
, ign_b
, wc
= set_up_depthy_working_copies(sbox
, empty
=True,
159 iota_path
= os
.path
.join(wc
, 'iota')
160 svntest
.main
.file_append(iota_path
, "new text\n")
162 # Commit in the "other" wc.
163 expected_output
= svntest
.wc
.State(wc
, { 'iota' : Item(verb
='Sending'), })
164 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
165 expected_status
.tweak('iota', wc_rev
=2, status
=' ')
166 svntest
.actions
.run_and_verify_commit(wc
,
169 None, None, None, None, None, wc
)
171 # Update the depth-empty wc, expecting not to receive the change to iota.
172 expected_output
= svntest
.wc
.State(wc_empty
, { })
173 expected_disk
= svntest
.wc
.State('', { })
174 expected_status
= svntest
.wc
.State(wc_empty
, { '' : svntest
.wc
.StateItem() })
175 expected_status
.tweak(contents
=None, status
=' ', wc_rev
=2)
176 svntest
.actions
.run_and_verify_update(wc_empty
,
180 None, None, None, None, None)
183 #----------------------------------------------------------------------
184 def depth_immediates_get_top_file_mod_only(sbox
):
185 "update depth-immediates wc gets top file mod only"
187 ign_a
, ign_b
, wc_immediates
, wc \
188 = set_up_depthy_working_copies(sbox
, immediates
=True, infinity
=True)
190 iota_path
= os
.path
.join(wc
, 'iota')
191 svntest
.main
.file_append(iota_path
, "new text in iota\n")
192 mu_path
= os
.path
.join(wc
, 'A', 'mu')
193 svntest
.main
.file_append(mu_path
, "new text in mu\n")
195 # Commit in the "other" wc.
196 expected_output
= svntest
.wc
.State(wc
,
197 { 'iota' : Item(verb
='Sending'),
198 'A/mu' : Item(verb
='Sending'),
200 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
201 expected_status
.tweak('iota', wc_rev
=2, status
=' ')
202 expected_status
.tweak('A/mu', wc_rev
=2, status
=' ')
203 svntest
.actions
.run_and_verify_commit(wc
,
206 None, None, None, None, None, wc
)
208 # Update the depth-immediates wc, expecting to receive only the
210 expected_output
= svntest
.wc
.State(wc_immediates
,
211 { 'iota' : Item(status
='U ') })
212 expected_disk
= svntest
.wc
.State('', { })
214 {'iota' : Item(contents
="This is the file 'iota'.\nnew text in iota\n"),
215 'A' : Item(contents
=None) } )
216 expected_status
= svntest
.wc
.State(wc_immediates
,
217 { '' : svntest
.wc
.StateItem() })
218 expected_status
.tweak(contents
=None, status
=' ', wc_rev
=2)
219 expected_status
.add(\
220 {'iota' : Item(status
=' ', wc_rev
=2),
221 'A' : Item(status
=' ', wc_rev
=2) } )
222 svntest
.actions
.run_and_verify_update(wc_immediates
,
226 None, None, None, None, None)
229 #----------------------------------------------------------------------
230 def depth_empty_commit(sbox
):
231 "commit a file from a depth-empty working copy"
232 # Bring iota into a depth-empty working copy, then commit a change to it.
233 wc_empty
, ign_a
, ign_b
, ign_c
= set_up_depthy_working_copies(sbox
,
236 # Form the working path of iota
237 wc_empty_iota
= os
.path
.join(wc_empty
, 'iota')
239 # Update 'iota' in the depth-empty working copy and modify it
240 svntest
.actions
.run_and_verify_svn(None, None, [],
242 svntest
.main
.file_write(wc_empty_iota
, "iota modified")
244 # Commit the modified changes from a depth-empty working copy
245 expected_output
= svntest
.wc
.State(wc_empty
, {
246 'iota' : Item(verb
='Sending'),
248 expected_status
= svntest
.wc
.State(wc_empty
, { })
249 expected_status
.add({
250 '' : Item(status
=' ', wc_rev
=1),
251 'iota' : Item(status
=' ', wc_rev
=2),
253 svntest
.actions
.run_and_verify_commit(wc_empty
,
256 None, None, None, None, None,
259 #----------------------------------------------------------------------
260 def depth_empty_with_file(sbox
):
261 "act on a file in a depth-empty working copy"
262 # Run 'svn up iota' to bring iota permanently into the working copy.
263 wc_empty
, ign_a
, ign_b
, wc
= set_up_depthy_working_copies(sbox
, empty
=True,
266 iota_path
= os
.path
.join(wc_empty
, 'iota')
267 if os
.path
.exists(iota_path
):
268 raise svntest
.Failure("'%s' exists when it shouldn't" % iota_path
)
270 # ### I'd love to do this using the recommended {expected_output,
271 # ### expected_status, expected_disk} method here, but after twenty
272 # ### minutes of trying to figure out how, I decided to compromise.
274 # Update iota by name, expecting to receive it.
275 svntest
.actions
.run_and_verify_svn(None, None, [], 'up', iota_path
)
277 # Test that we did receive it.
278 if not os
.path
.exists(iota_path
):
279 raise svntest
.Failure("'%s' doesn't exist when it should" % iota_path
)
281 # Commit a change to iota in the "other" wc.
282 other_iota_path
= os
.path
.join(wc
, 'iota')
283 svntest
.main
.file_append(other_iota_path
, "new text\n")
284 expected_output
= svntest
.wc
.State(wc
, { 'iota' : Item(verb
='Sending'), })
285 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
286 expected_status
.tweak('iota', wc_rev
=2, status
=' ')
287 svntest
.actions
.run_and_verify_commit(wc
,
290 None, None, None, None, None, wc
)
292 # Delete iota in the "other" wc.
293 other_iota_path
= os
.path
.join(wc
, 'iota')
294 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', other_iota_path
)
295 expected_output
= svntest
.wc
.State(wc
, { 'iota' : Item(verb
='Deleting'), })
296 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
297 expected_status
.remove('iota')
298 svntest
.actions
.run_and_verify_commit(wc
,
301 None, None, None, None, None, wc
)
303 # Update the depth-empty wc just a little, expecting to receive
304 # the change in iota.
305 expected_output
= svntest
.wc
.State(\
306 wc_empty
, { 'iota' : Item(status
='U ') })
307 expected_disk
= svntest
.wc
.State(\
308 '', { 'iota' : Item(contents
="This is the file 'iota'.\nnew text\n") })
309 expected_status
= svntest
.wc
.State(wc_empty
,
310 { '' : Item(status
=' ', wc_rev
=2),
311 'iota' : Item(status
=' ', wc_rev
=2),})
312 svntest
.actions
.run_and_verify_update(wc_empty
,
316 None, None, None, None, None, False,
319 # Update the depth-empty wc all the way, expecting to receive the deletion
321 expected_output
= svntest
.wc
.State(\
322 wc_empty
, { 'iota' : Item(status
='D ') })
323 expected_disk
= svntest
.wc
.State('', { })
324 expected_status
= svntest
.wc
.State(\
325 wc_empty
, { '' : Item(status
=' ', wc_rev
=3) })
326 svntest
.actions
.run_and_verify_update(wc_empty
,
330 None, None, None, None, None)
333 #----------------------------------------------------------------------
334 def depth_empty_with_dir(sbox
):
335 "bring a dir into a depth-empty working copy"
336 # Run 'svn up A' to bring A permanently into the working copy.
337 wc_empty
, ign_a
, ign_b
, wc
= set_up_depthy_working_copies(sbox
, empty
=True,
340 A_path
= os
.path
.join(wc_empty
, 'A')
341 other_mu_path
= os
.path
.join(wc
, 'A', 'mu')
343 # We expect A to be added at depth infinity, so a normal 'svn up A'
344 # should be sufficient to add all descendants.
345 expected_output
= svntest
.wc
.State(wc_empty
, {
346 'A' : Item(status
='A '),
347 'A/mu' : Item(status
='A '),
348 'A/B' : Item(status
='A '),
349 'A/B/lambda' : Item(status
='A '),
350 'A/B/E' : Item(status
='A '),
351 'A/B/E/alpha' : Item(status
='A '),
352 'A/B/E/beta' : Item(status
='A '),
353 'A/B/F' : Item(status
='A '),
354 'A/C' : Item(status
='A '),
355 'A/D' : Item(status
='A '),
356 'A/D/gamma' : Item(status
='A '),
357 'A/D/G' : Item(status
='A '),
358 'A/D/G/pi' : Item(status
='A '),
359 'A/D/G/rho' : Item(status
='A '),
360 'A/D/G/tau' : Item(status
='A '),
361 'A/D/H' : Item(status
='A '),
362 'A/D/H/chi' : Item(status
='A '),
363 'A/D/H/psi' : Item(status
='A '),
364 'A/D/H/omega' : Item(status
='A ')
366 expected_disk
= svntest
.main
.greek_state
.copy()
367 expected_disk
.remove('iota')
368 expected_status
= svntest
.actions
.get_virginal_state(wc_empty
, 1)
369 expected_status
.remove('iota')
370 svntest
.actions
.run_and_verify_update(wc_empty
,
375 None, None, None, None,
378 # Commit a change to A/mu in the "other" wc.
379 svntest
.main
.file_write(other_mu_path
, "new text\n")
380 expected_output
= svntest
.wc
.State(\
381 wc
, { 'A/mu' : Item(verb
='Sending'), })
382 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
383 expected_status
.tweak('A/mu', wc_rev
=2, status
=' ')
384 svntest
.actions
.run_and_verify_commit(wc
,
387 None, None, None, None, None, wc
)
389 # Update "A" by name in wc_empty, expect to receive the change to A/mu.
390 expected_output
= svntest
.wc
.State(wc_empty
, { 'A/mu' : Item(status
='U ') })
391 expected_disk
= svntest
.main
.greek_state
.copy()
392 expected_disk
.remove('iota')
393 expected_disk
.tweak('A/mu', contents
='new text\n')
394 expected_status
= svntest
.actions
.get_virginal_state(wc_empty
, 2)
395 expected_status
.remove('iota')
396 expected_status
.tweak('', wc_rev
=1)
397 svntest
.actions
.run_and_verify_update(wc_empty
,
402 None, None, None, None,
405 # Commit the deletion of A/mu from the "other" wc.
406 svntest
.main
.file_write(other_mu_path
, "new text\n")
407 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', other_mu_path
)
408 expected_output
= svntest
.wc
.State(wc
, { 'A/mu' : Item(verb
='Deleting'), })
409 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
410 expected_status
.remove('A/mu')
411 svntest
.actions
.run_and_verify_commit(wc
,
414 None, None, None, None, None, wc
)
417 # Update "A" by name in wc_empty, expect to A/mu to disappear.
418 expected_output
= svntest
.wc
.State(wc_empty
, { 'A/mu' : Item(status
='D ') })
419 expected_disk
= svntest
.main
.greek_state
.copy()
420 expected_disk
.remove('iota')
421 expected_disk
.remove('A/mu')
422 expected_status
= svntest
.actions
.get_virginal_state(wc_empty
, 3)
423 expected_status
.remove('iota')
424 expected_status
.remove('A/mu')
425 expected_status
.tweak('', wc_rev
=1)
426 svntest
.actions
.run_and_verify_update(wc_empty
,
431 None, None, None, None,
436 #----------------------------------------------------------------------
437 def depth_immediates_bring_in_file(sbox
):
438 "bring a file into a depth-immediates working copy"
440 # Create an immediates working copy and form the paths
441 ign_a
, ign_b
, wc_imm
, wc
= set_up_depthy_working_copies(sbox
,
443 A_mu_path
= os
.path
.join(wc_imm
, 'A', 'mu')
444 gamma_path
= os
.path
.join(wc_imm
, 'A', 'D', 'gamma')
446 # Run 'svn up A/mu' to bring A/mu permanently into the working copy.
447 expected_output
= svntest
.wc
.State(wc_imm
, {
448 'A/mu' : Item(status
='A '),
450 expected_disk
= svntest
.main
.greek_state
.copy()
451 expected_disk
.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
452 'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
453 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
454 'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
455 expected_status
= svntest
.actions
.get_virginal_state(wc_imm
, 1)
456 expected_status
.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
457 'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
458 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
459 'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
460 svntest
.actions
.run_and_verify_update(wc_imm
,
468 # Run 'svn up A/D/gamma' to test the edge case 'Skipped'.
469 expected_output
= svntest
.wc
.State(wc_imm
, {
470 'A/D/gamma' : Item(verb
='Skipped'),
472 expected_disk
= svntest
.main
.greek_state
.copy()
473 expected_disk
.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
474 'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
475 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
476 'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
477 expected_status
= svntest
.actions
.get_virginal_state(wc_imm
, 1)
478 expected_status
.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
479 'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
480 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
481 'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
482 svntest
.actions
.run_and_verify_update(wc_imm
,
490 #----------------------------------------------------------------------
491 def depth_immediates_fill_in_dir(sbox
):
492 "bring a dir into a depth-immediates working copy"
494 # Run 'svn up A' to fill in A as a depth-infinity subdir.
495 ign_a
, ign_b
, wc_immediates
, wc \
496 = set_up_depthy_working_copies(sbox
, immediates
=True)
497 A_path
= os
.path
.join(wc_immediates
, 'A')
498 expected_output
= svntest
.wc
.State(wc_immediates
, {
499 'A/mu' : Item(status
='A '),
500 'A/B' : Item(status
='A '),
501 'A/B/lambda' : Item(status
='A '),
502 'A/B/E' : Item(status
='A '),
503 'A/B/E/alpha' : Item(status
='A '),
504 'A/B/E/beta' : Item(status
='A '),
505 'A/B/F' : Item(status
='A '),
506 'A/C' : Item(status
='A '),
507 'A/D' : Item(status
='A '),
508 'A/D/gamma' : Item(status
='A '),
509 'A/D/G' : Item(status
='A '),
510 'A/D/G/pi' : Item(status
='A '),
511 'A/D/G/rho' : Item(status
='A '),
512 'A/D/G/tau' : Item(status
='A '),
513 'A/D/H' : Item(status
='A '),
514 'A/D/H/chi' : Item(status
='A '),
515 'A/D/H/psi' : Item(status
='A '),
516 'A/D/H/omega' : Item(status
='A ')
518 expected_disk
= svntest
.main
.greek_state
.copy()
519 expected_status
= svntest
.actions
.get_virginal_state(wc_immediates
, 1)
520 svntest
.actions
.run_and_verify_update(wc_immediates
,
525 None, None, None, None,
526 '--depth', 'infinity',
529 #----------------------------------------------------------------------
530 def depth_mixed_bring_in_dir(sbox
):
531 "bring a dir into a mixed-depth working copy"
533 # Run 'svn up --depth=immediates A' in a depth-empty working copy.
534 wc_empty
, ign_a
, ign_b
, wc
= set_up_depthy_working_copies(sbox
, empty
=True)
535 A_path
= os
.path
.join(wc_empty
, 'A')
536 B_path
= os
.path
.join(wc_empty
, 'A', 'B')
537 C_path
= os
.path
.join(wc_empty
, 'A', 'C')
539 expected_output
= svntest
.wc
.State(wc_empty
, {
540 'A' : Item(status
='A '),
541 'A/mu' : Item(status
='A '),
543 expected_disk
= svntest
.main
.greek_state
.copy()
544 expected_disk
.remove('iota', 'A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
545 'A/B/E/beta', 'A/B/F', 'A/C', 'A/D', 'A/D/gamma',
546 'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
547 'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
548 expected_status
= svntest
.actions
.get_virginal_state(wc_empty
, 1)
549 expected_status
.remove('iota', 'A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
550 'A/B/E/beta', 'A/B/F', 'A/C', 'A/D', 'A/D/gamma',
551 'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
552 'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
553 svntest
.actions
.run_and_verify_update(wc_empty
,
558 None, None, None, None,
561 # Check that A was added at depth=files.
562 svntest
.actions
.run_and_verify_svn(None, "Depth: files|Path.+|URL.+|" \
563 "Repository.+|Revision.+|Node Kind.+|" \
564 "Schedule.+|Last.+|\n", [], "info",
567 # Now, bring in A/B at depth-immediates.
568 expected_output
= svntest
.wc
.State(wc_empty
, {
569 'A/B' : Item(status
='A '),
570 'A/B/lambda' : Item(status
='A '),
571 'A/B/E' : Item(status
='A '),
572 'A/B/F' : Item(status
='A '),
574 expected_disk
= svntest
.main
.greek_state
.copy()
575 expected_disk
.remove('iota', 'A/B/E/alpha', 'A/B/E/beta', 'A/C',
576 'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
577 'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
579 expected_status
= svntest
.actions
.get_virginal_state(wc_empty
, 1)
580 expected_status
.remove('iota', 'A/B/E/alpha', 'A/B/E/beta', 'A/C',
581 'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
582 'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
584 svntest
.actions
.run_and_verify_update(wc_empty
,
589 None, None, None, None,
590 '--depth', 'immediates',
592 # Check that A/B was added at depth=immediates.
593 svntest
.actions
.run_and_verify_svn(None, "Depth: immediates|Path.+|URL.+|" \
594 "Repository.+|Revision.+|Node Kind.+|" \
595 "Schedule.+|Last.+|\n", [], "info",
598 # Now, bring in A/C at depth-empty.
599 expected_output
= svntest
.wc
.State(wc_empty
, {
600 'A/C' : Item(status
='A '),
602 expected_disk
= svntest
.main
.greek_state
.copy()
603 expected_disk
.remove('iota', 'A/B/E/alpha', 'A/B/E/beta',
604 'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
605 'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
607 expected_status
= svntest
.actions
.get_virginal_state(wc_empty
, 1)
608 expected_status
.remove('iota', 'A/B/E/alpha', 'A/B/E/beta',
609 'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
610 'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
612 svntest
.actions
.run_and_verify_update(wc_empty
,
617 None, None, None, None,
620 # Check that A/C was added at depth=empty.
621 svntest
.actions
.run_and_verify_svn(None, "Depth: empty|Path.+|URL.+|" \
622 "Repository.+|Revision.+|Node Kind.+|" \
623 "Schedule.+|Last.+|\n", [], "info",
626 #----------------------------------------------------------------------
627 def depth_empty_unreceive_delete(sbox
):
628 "depth-empty working copy ignores a deletion"
629 # Check out a depth-empty greek tree to wc1. In wc2, delete iota and
630 # commit. Update wc1; should not receive the delete.
631 wc_empty
, ign_a
, ign_b
, wc
= set_up_depthy_working_copies(sbox
, empty
=True,
634 iota_path
= os
.path
.join(wc
, 'iota')
636 # Commit in the "other" wc.
637 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', iota_path
)
638 expected_output
= svntest
.wc
.State(wc
, { 'iota' : Item(verb
='Deleting'), })
639 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
640 expected_status
.remove('iota')
641 svntest
.actions
.run_and_verify_commit(wc
,
644 None, None, None, None, None, wc
)
646 # Update the depth-empty wc, expecting not to receive the deletion of iota.
647 expected_output
= svntest
.wc
.State(wc_empty
, { })
648 expected_disk
= svntest
.wc
.State('', { })
649 expected_status
= svntest
.wc
.State(wc_empty
, { '' : svntest
.wc
.StateItem() })
650 expected_status
.tweak(contents
=None, status
=' ', wc_rev
=2)
651 svntest
.actions
.run_and_verify_update(wc_empty
,
655 None, None, None, None, None)
658 #----------------------------------------------------------------------
659 def depth_immediates_unreceive_delete(sbox
):
660 "depth-immediates working copy ignores a deletion"
661 # Check out a depth-immediates greek tree to wc1. In wc2, delete
662 # A/mu and commit. Update wc1; should not receive the delete.
664 ign_a
, ign_b
, wc_immed
, wc
= set_up_depthy_working_copies(sbox
,
668 mu_path
= os
.path
.join(wc
, 'A', 'mu')
670 # Commit in the "other" wc.
671 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', mu_path
)
672 expected_output
= svntest
.wc
.State(wc
, { 'A/mu' : Item(verb
='Deleting'), })
673 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
674 expected_status
.remove('A/mu')
675 svntest
.actions
.run_and_verify_commit(wc
,
678 None, None, None, None, None, wc
)
680 # Update the depth-immediates wc, expecting not to receive the deletion
682 expected_output
= svntest
.wc
.State(wc_immed
, { })
683 expected_disk
= svntest
.wc
.State('', {
684 'iota' : Item(contents
="This is the file 'iota'.\n"),
687 expected_status
= svntest
.wc
.State(wc_immed
, {
688 '' : Item(status
=' ', wc_rev
=2),
689 'iota' : Item(status
=' ', wc_rev
=2),
690 'A' : Item(status
=' ', wc_rev
=2)
692 svntest
.actions
.run_and_verify_update(wc_immed
,
696 None, None, None, None, None)
698 #----------------------------------------------------------------------
699 def depth_immediates_receive_delete(sbox
):
700 "depth-immediates working copy receives a deletion"
701 # Check out a depth-immediates greek tree to wc1. In wc2, delete A and
702 # commit. Update wc1 should receive the delete.
704 ign_a
, ign_b
, wc_immed
, wc
= set_up_depthy_working_copies(sbox
,
708 A_path
= os
.path
.join(wc
, 'A')
710 # Commit in the "other" wc.
711 svntest
.actions
.run_and_verify_svn(None, None, [], 'rm', A_path
)
712 expected_output
= svntest
.wc
.State(wc
, { 'A' : Item(verb
='Deleting'), })
713 expected_status
= svntest
.wc
.State(wc
, {
714 '' : Item(status
=' ', wc_rev
=1),
715 'iota' : Item(status
=' ', wc_rev
=1),
717 svntest
.actions
.run_and_verify_commit(wc
,
720 None, None, None, None, None, wc
)
722 # Update the depth-immediates wc, expecting to receive the deletion of A.
723 expected_output
= svntest
.wc
.State(wc_immed
, {
724 'A' : Item(status
='D ')
726 expected_disk
= svntest
.wc
.State('', {
727 'iota' : Item(contents
="This is the file 'iota'.\n"),
729 expected_status
= svntest
.wc
.State(wc_immed
, {
730 '' : Item(status
=' ', wc_rev
=2),
731 'iota' : Item(status
=' ', wc_rev
=2)
733 svntest
.actions
.run_and_verify_update(wc_immed
,
737 None, None, None, None, None)
739 #----------------------------------------------------------------------
740 def depth_immediates_subdir_propset_1(sbox
):
741 "depth-immediates commit subdir propset, update"
742 ign_a
, ign_b
, wc_immediates
, ign_c \
743 = set_up_depthy_working_copies(sbox
, immediates
=True)
745 A_path
= os
.path
.join(wc_immediates
, 'A')
747 # Set a property on an immediate subdirectory of the working copy.
748 svntest
.actions
.run_and_verify_svn(None, None, [],
749 'pset', 'foo', 'bar',
752 # Create expected output tree.
753 expected_output
= svntest
.wc
.State(wc_immediates
, {
754 'A' : Item(verb
='Sending'),
757 # Create expected status tree.
758 expected_status
= svntest
.wc
.State(wc_immediates
, {
759 '' : Item(status
=' ', wc_rev
=1),
760 'iota' : Item(status
=' ', wc_rev
=1),
761 'A' : Item(status
=' ', wc_rev
=2)
764 # Commit wc_immediates/A.
765 svntest
.actions
.run_and_verify_commit(wc_immediates
,
773 # Create expected output tree for the update.
774 expected_output
= svntest
.wc
.State(wc_immediates
, { })
776 # Create expected disk tree.
777 expected_disk
= svntest
.wc
.State('', {
778 'iota' : Item(contents
="This is the file 'iota'.\n"),
779 'A' : Item(contents
=None, props
={'foo' : 'bar'}),
782 expected_status
.tweak(contents
=None, status
=' ', wc_rev
=2)
784 # Update the depth-immediates wc.
785 svntest
.actions
.run_and_verify_update(wc_immediates
,
789 None, None, None, None, None, 1)
791 #----------------------------------------------------------------------
792 def depth_immediates_subdir_propset_2(sbox
):
793 "depth-immediates update receives subdir propset"
797 # Make the other working copy.
798 other_wc
= sbox
.add_wc_path('other')
799 svntest
.actions
.duplicate_dir(wc_dir
, other_wc
)
801 A_path
= os
.path
.join(wc_dir
, 'A')
803 # Set a property on an immediate subdirectory of the working copy.
804 svntest
.actions
.run_and_verify_svn(None, None, [],
805 'pset', 'foo', 'bar',
808 svntest
.actions
.run_and_verify_svn(None, None, [],
809 'commit', '-m', 'logmsg', A_path
)
811 # Update at depth=immediates in the other wc, expecting to see no errors.
812 svntest
.actions
.run_and_verify_svn("Output on stderr where none expected",
813 svntest
.verify
.AnyOutput
, [],
814 'update', '--depth', 'immediates',
817 #----------------------------------------------------------------------
818 def depth_update_to_more_depth(sbox
):
819 "gradually update an empty wc to depth=infinity"
821 wc_dir
, ign_a
, ign_b
, ign_c
= set_up_depthy_working_copies(sbox
, empty
=True)
825 # Run 'svn up --depth=files' in a depth-empty working copy.
826 expected_output
= svntest
.wc
.State('', {
827 'iota' : Item(status
='A '),
829 expected_status
= svntest
.wc
.State('', {
830 '' : Item(status
=' ', wc_rev
=1),
831 'iota' : Item(status
=' ', wc_rev
=1),
833 expected_disk
= svntest
.wc
.State('', {
834 'iota' : Item("This is the file 'iota'.\n"),
836 svntest
.actions
.run_and_verify_update('',
841 None, None, None, None,
843 svntest
.actions
.run_and_verify_svn(None, "Depth: files|Path.+|URL.+|" \
844 "Repository.+|Revision.+|Node Kind.+|" \
845 "Schedule.+|Last.+|\n", [], "info")
847 # Run 'svn up --depth=immediates' in the now depth-files working copy.
848 expected_output
= svntest
.wc
.State('', {
849 'A' : Item(status
='A '),
851 expected_status
= svntest
.wc
.State('', {
852 '' : Item(status
=' ', wc_rev
=1),
853 'iota' : Item(status
=' ', wc_rev
=1),
854 'A' : Item(status
=' ', wc_rev
=1),
856 expected_disk
= svntest
.wc
.State('', {
857 'iota' : Item("This is the file 'iota'.\n"),
860 svntest
.actions
.run_and_verify_update('',
865 None, None, None, None,
866 '--depth', 'immediates')
867 svntest
.actions
.run_and_verify_svn(None, "Depth: immediates|Path.+|URL.+|" \
868 "Repository.+|Revision.+|Node Kind.+|" \
869 "Schedule.+|Last.+|\n", [], "info")
870 svntest
.actions
.run_and_verify_svn(None, "Depth: empty|Path.+|URL.+|" \
871 "Repository.+|Revision.+|Node Kind.+|" \
872 "Schedule.+|Last.+|\n", [], "info", "A")
874 # Upgrade 'A' to depth-files.
875 expected_output
= svntest
.wc
.State('', {
876 'A/mu' : Item(status
='A '),
878 expected_status
= svntest
.wc
.State('', {
879 '' : Item(status
=' ', wc_rev
=1),
880 'iota' : Item(status
=' ', wc_rev
=1),
881 'A' : Item(status
=' ', wc_rev
=1),
882 'A/mu' : Item(status
=' ', wc_rev
=1),
884 expected_disk
= svntest
.wc
.State('', {
885 'iota' : Item("This is the file 'iota'.\n"),
887 'A/mu' : Item("This is the file 'mu'.\n"),
889 svntest
.actions
.run_and_verify_update('',
894 None, None, None, None,
895 '--depth', 'files', 'A')
896 svntest
.actions
.run_and_verify_svn(None, "Depth: immediates|Path.+|URL.+|" \
897 "Repository.+|Revision.+|Node Kind.+|" \
898 "Schedule.+|Last.+|\n", [], "info")
899 svntest
.actions
.run_and_verify_svn(None, "Depth: files|Path.+|URL.+|" \
900 "Repository.+|Revision.+|Node Kind.+|" \
901 "Schedule.+|Last.+|\n", [], "info", "A")
903 # Run 'svn up --depth=infinity' in the working copy.
904 expected_output
= svntest
.wc
.State('', {
905 'A/B' : Item(status
='A '),
906 'A/B/lambda' : Item(status
='A '),
907 'A/B/E' : Item(status
='A '),
908 'A/B/E/alpha' : Item(status
='A '),
909 'A/B/E/beta' : Item(status
='A '),
910 'A/B/F' : Item(status
='A '),
911 'A/C' : Item(status
='A '),
912 'A/D' : Item(status
='A '),
913 'A/D/gamma' : Item(status
='A '),
914 'A/D/G' : Item(status
='A '),
915 'A/D/G/pi' : Item(status
='A '),
916 'A/D/G/rho' : Item(status
='A '),
917 'A/D/G/tau' : Item(status
='A '),
918 'A/D/H' : Item(status
='A '),
919 'A/D/H/chi' : Item(status
='A '),
920 'A/D/H/psi' : Item(status
='A '),
921 'A/D/H/omega' : Item(status
='A ')
923 expected_disk
= svntest
.main
.greek_state
.copy()
924 expected_status
= svntest
.actions
.get_virginal_state('', 1)
925 svntest
.actions
.run_and_verify_update('',
930 None, None, None, None,
931 '--depth', 'infinity')
932 # svn info doesn't print a 'Depth:' line for infinity, so we verify
933 # that no such line is present in the output.
934 output1
, err
= svntest
.actions
.run_and_verify_svn(None, None, [], "info")
935 output2
, err
= svntest
.actions
.run_and_verify_svn(None, None, [], "info", "A")
936 for line
in output1
+ output2
:
937 if line
.startswith("Depth:"):
938 raise svntest
.Failure("Non-infinity depth detected after an upgrade \
941 def commit_propmods_with_depth_empty(sbox
):
942 "commit property mods only, using --depth=empty"
946 iota_path
= os
.path
.join(wc_dir
, 'iota')
947 A_path
= os
.path
.join(wc_dir
, 'A')
948 D_path
= os
.path
.join(A_path
, 'D')
949 gamma_path
= os
.path
.join(D_path
, 'gamma')
950 G_path
= os
.path
.join(D_path
, 'G')
951 pi_path
= os
.path
.join(G_path
, 'pi')
952 H_path
= os
.path
.join(D_path
, 'H')
953 chi_path
= os
.path
.join(H_path
, 'chi')
955 # Set some properties, modify some files.
956 svntest
.actions
.run_and_verify_svn(None, None, [],
957 'propset', 'foo', 'foo-val', wc_dir
)
958 svntest
.actions
.run_and_verify_svn(None, None, [],
959 'propset', 'bar', 'bar-val', D_path
)
960 svntest
.actions
.run_and_verify_svn(None, None, [],
961 'propset', 'baz', 'baz-val', G_path
)
962 svntest
.actions
.run_and_verify_svn(None, None, [],
963 'propset', 'qux', 'qux-val', H_path
)
964 svntest
.main
.file_append(iota_path
, "new iota\n")
965 svntest
.main
.file_append(gamma_path
, "new gamma\n")
966 svntest
.main
.file_append(pi_path
, "new pi\n")
967 svntest
.main
.file_append(chi_path
, "new chi\n")
969 # The only things that should be committed are two of the propsets.
970 expected_output
= svntest
.wc
.State(
972 { '' : Item(verb
='Sending'),
973 'A/D' : Item(verb
='Sending'), }
975 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
976 # Expect the two propsets to be committed:
977 expected_status
.tweak('', status
=' ', wc_rev
=2)
978 expected_status
.tweak('A/D', status
=' ', wc_rev
=2)
979 # Expect every other change to remain uncommitted:
980 expected_status
.tweak('iota', status
='M ', wc_rev
=1)
981 expected_status
.tweak('A/D/G', status
=' M', wc_rev
=1)
982 expected_status
.tweak('A/D/H', status
=' M', wc_rev
=1)
983 expected_status
.tweak('A/D/gamma', status
='M ', wc_rev
=1)
984 expected_status
.tweak('A/D/G/pi', status
='M ', wc_rev
=1)
985 expected_status
.tweak('A/D/H/chi', status
='M ', wc_rev
=1)
987 svntest
.actions
.run_and_verify_commit(wc_dir
,
996 # Test for issue #2845.
997 def diff_in_depthy_wc(sbox
):
998 "diff at various depths in non-infinity wc"
1000 wc_empty
, ign_a
, ign_b
, wc
= set_up_depthy_working_copies(sbox
, empty
=True,
1003 iota_path
= os
.path
.join(wc
, 'iota')
1004 A_path
= os
.path
.join(wc
, 'A')
1005 mu_path
= os
.path
.join(wc
, 'A', 'mu')
1006 gamma_path
= os
.path
.join(wc
, 'A', 'D', 'gamma')
1008 # Make some changes in the depth-infinity wc, and commit them
1009 svntest
.actions
.run_and_verify_svn(None, None, [],
1010 'propset', 'foo', 'foo-val', wc
)
1011 svntest
.main
.file_write(iota_path
, "new text\n")
1012 svntest
.actions
.run_and_verify_svn(None, None, [],
1013 'propset', 'bar', 'bar-val', A_path
)
1014 svntest
.main
.file_write(mu_path
, "new text\n")
1015 svntest
.main
.file_write(gamma_path
, "new text\n")
1016 svntest
.actions
.run_and_verify_svn(None, None, [],
1017 'commit', '-m', '', wc
)
1021 "Property changes on: .\n",
1022 "___________________________________________________________________\n",
1027 "===================================================================\n",
1028 "--- iota\t(revision 2)\n",
1029 "+++ iota\t(working copy)\n",
1032 "+This is the file 'iota'.\n",
1033 "Property changes on: A\n",
1034 "___________________________________________________________________\n",
1040 "===================================================================\n",
1041 "--- A/mu\t(revision 2)\n",
1042 "+++ A/mu\t(working copy)\n",
1045 "+This is the file 'mu'.\n" ]
1049 expected_output
= svntest
.verify
.UnorderedOutput(diff
[:6])
1050 # The diff should contain only the propchange on '.'
1051 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1054 # Upgrade to depth-files.
1055 svntest
.actions
.run_and_verify_svn(None, None, [], 'up',
1056 '--depth', 'files', '-r1')
1057 # The diff should contain only the propchange on '.' and the
1058 # contents change on iota.
1059 expected_output
= svntest
.verify
.UnorderedOutput(diff
[:13])
1060 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1062 # Do a diff at --depth empty.
1063 expected_output
= svntest
.verify
.UnorderedOutput(diff
[:6])
1064 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1065 'diff', '--depth', 'empty', '-rHEAD')
1067 # Upgrade to depth-immediates.
1068 svntest
.actions
.run_and_verify_svn(None, None, [], 'up',
1069 '--depth', 'immediates', '-r1')
1070 # The diff should contain the propchanges on '.' and 'A' and the
1071 # contents change on iota.
1072 expected_output
= svntest
.verify
.UnorderedOutput(diff
[:19])
1073 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1075 # Do a diff at --depth files.
1076 expected_output
= svntest
.verify
.UnorderedOutput(diff
[:13])
1077 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1078 'diff', '--depth', 'files', '-rHEAD')
1080 # Upgrade A to depth-files.
1081 svntest
.actions
.run_and_verify_svn(None, None, [], 'up',
1082 '--depth', 'files', '-r1', 'A')
1083 # The diff should contain everything but the contents change on
1084 # gamma (which does not exist in this working copy).
1085 expected_output
= svntest
.verify
.UnorderedOutput(diff
)
1086 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1088 # Do a diff at --depth immediates.
1089 expected_output
= svntest
.verify
.UnorderedOutput(diff
[:19])
1090 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1091 'diff', '--depth', 'immediates', '-rHEAD')
1093 def commit_depth_immediates(sbox
):
1094 "commit some files with --depth=immediates"
1096 wc_dir
= sbox
.wc_dir
1098 # Test the fix for some bugs Mike Pilato reported here:
1100 # http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=128509
1101 # From: "C. Michael Pilato" <cmpilato@collab.net>
1102 # To: Karl Fogel <kfogel@red-bean.com>
1103 # CC: dev@subversion.tigris.org
1104 # References: <87d4yzcrro.fsf@red-bean.com>
1105 # Subject: Re: [PATCH] Make 'svn commit --depth=foo' work.
1106 # Message-ID: <46968831.2070906@collab.net>
1107 # Date: Thu, 12 Jul 2007 15:59:45 -0400
1109 # See also http://subversion.tigris.org/issues/show_bug.cgi?id=2882.
1111 # Outline of the test:
1112 # ====================
1114 # Modify these three files:
1120 # Then commit some of them using --depth=immediates:
1122 # svn ci -m "log msg" --depth=immediates wc_dir wc_dir/A/D/G/rho
1124 # Before the bugfix, that would result in an error:
1126 # subversion/libsvn_wc/lock.c:570: (apr_err=155004)
1127 # svn: Working copy '/blah/blah/blah/wc' locked
1128 # svn: run 'svn cleanup' to remove locks \
1129 # (type 'svn help cleanup' for details)
1131 # After the bugfix, it correctly commits two of the three files:
1135 # Transmitting file data ..
1136 # Committed revision 2.
1138 iota_path
= os
.path
.join(wc_dir
, 'iota')
1139 mu_path
= os
.path
.join(wc_dir
, 'A', 'mu')
1140 G_path
= os
.path
.join(wc_dir
, 'A', 'D', 'G')
1141 rho_path
= os
.path
.join(G_path
, 'rho')
1143 svntest
.main
.file_append(iota_path
, "new text in iota\n")
1144 svntest
.main
.file_append(mu_path
, "new text in mu\n")
1145 svntest
.main
.file_append(rho_path
, "new text in rho\n")
1147 expected_output
= svntest
.wc
.State(wc_dir
, {
1148 'iota' : Item(verb
='Sending'),
1149 'A/D/G/rho' : Item(verb
='Sending'),
1151 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1152 expected_status
.tweak('iota', status
=' ', wc_rev
=2)
1153 expected_status
.tweak('A/mu', status
='M ', wc_rev
=1)
1154 expected_status
.tweak('A/D/G/rho', status
=' ', wc_rev
=2)
1155 svntest
.actions
.run_and_verify_commit(wc_dir
,
1161 '--depth', 'immediates',
1164 def depth_immediates_receive_new_dir(sbox
):
1165 "depth-immediates wc receives new directory"
1167 ign_a
, ign_b
, wc_immed
, wc
= set_up_depthy_working_copies(sbox
,
1171 I_path
= os
.path
.join(wc
, 'I')
1172 zeta_path
= os
.path
.join(wc
, 'I', 'zeta')
1173 other_I_path
= os
.path
.join(wc_immed
, 'I')
1176 svntest
.main
.file_write(zeta_path
, "This is the file 'zeta'.\n")
1178 # Commit in the "other" wc.
1179 svntest
.actions
.run_and_verify_svn(None, None, [], 'add', I_path
)
1180 expected_output
= svntest
.wc
.State(wc
, {
1181 'I' : Item(verb
='Adding'),
1182 'I/zeta' : Item(verb
='Adding'),
1184 expected_status
= svntest
.actions
.get_virginal_state(wc
, 1)
1185 expected_status
.add({
1186 'I' : Item(status
=' ', wc_rev
=2),
1187 'I/zeta' : Item(status
=' ', wc_rev
=2),
1189 svntest
.actions
.run_and_verify_commit(wc
,
1192 None, None, None, None, None, wc
)
1194 # Update the depth-immediates wc, expecting to receive just the
1195 # new directory, without the file.
1196 expected_output
= svntest
.wc
.State(wc_immed
, {
1197 'I' : Item(status
='A '),
1199 expected_disk
= svntest
.wc
.State('', {
1200 'iota' : Item(contents
="This is the file 'iota'.\n"),
1204 expected_status
= svntest
.wc
.State(wc_immed
, {
1205 '' : Item(status
=' ', wc_rev
=2),
1206 'iota' : Item(status
=' ', wc_rev
=2),
1207 'A' : Item(status
=' ', wc_rev
=2),
1208 'I' : Item(status
=' ', wc_rev
=2),
1210 svntest
.actions
.run_and_verify_update(wc_immed
,
1214 None, None, None, None, None)
1215 # Check that the new directory was added at depth=empty.
1216 svntest
.actions
.run_and_verify_svn(None, "Depth: empty|Path.+|URL.+|" \
1217 "Repository.+|Revision.+|Node Kind.+|" \
1218 "Schedule.+|Last.+|\n", [], "info",
1221 def add_tree_with_depth_files(sbox
):
1222 "add multi-subdir tree with --depth=files" # For issue #2931
1224 wc_dir
= sbox
.wc_dir
1225 new1_path
= os
.path
.join(wc_dir
, 'new1')
1226 new2_path
= os
.path
.join(new1_path
, 'new2')
1229 svntest
.actions
.run_and_verify_svn(None, None, [],
1230 "add", "--depth", "files", new1_path
)
1232 def upgrade_from_above(sbox
):
1233 "upgrade a depth=empty wc from above"
1235 # The bug was that 'svn up --depth=files' worked from within the
1236 # working copy, but not from without with working copy top given
1237 # as an argument. Both ways would correctly cause 'iota' to
1238 # appear, but only the former actually upgraded the depth of the
1239 # working copy to 'files'. See this thread for details:
1241 # http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=130157
1242 # From: Alexander Sinyushkin <Alexander.Sinyushkin@svnkit.com>
1243 # To: dev@subversion.tigris.org
1244 # Subject: Problem upgrading working copy depth
1245 # Date: Wed, 19 Sep 2007 23:15:24 +0700
1246 # Message-ID: <46F14B1C.8010406@svnkit.com>
1248 wc
, ign_a
, ign_b
, ign_c
= set_up_depthy_working_copies(sbox
, empty
=True)
1250 # First verify that upgrading from within works.
1251 saved_cwd
= os
.getcwd()
1254 expected_output
= svntest
.wc
.State('', {
1255 'iota' : Item(status
='A '),
1257 expected_disk
= svntest
.wc
.State('', {
1258 'iota' : Item(contents
="This is the file 'iota'.\n"),
1260 expected_status
= svntest
.wc
.State('', {
1261 '' : Item(status
=' ', wc_rev
=1),
1262 'iota' : Item(status
=' ', wc_rev
=1),
1264 svntest
.actions
.run_and_verify_update('',
1268 None, None, None, None, None, None,
1270 svntest
.actions
.run_and_verify_svn(None, "Depth: +files|Path.+|URL.+|" \
1271 "Repository.+|Revision.+|Node Kind.+|" \
1272 "Schedule.+|Last.+|\n", [], "info")
1276 # Reset and do it again, this time from above the working copy.
1277 svntest
.main
.safe_rmtree(wc
)
1278 wc
, ign_a
, ign_b
, ign_c
= set_up_depthy_working_copies(sbox
, empty
=True)
1279 expected_output
= svntest
.wc
.State(wc
, {
1280 'iota' : Item(status
='A '),
1282 expected_disk
= svntest
.wc
.State('', {
1283 'iota' : Item(contents
="This is the file 'iota'.\n"),
1285 expected_status
= svntest
.wc
.State(wc
, {
1286 '' : Item(status
=' ', wc_rev
=1),
1287 'iota' : Item(status
=' ', wc_rev
=1),
1289 svntest
.actions
.run_and_verify_update(wc
,
1293 None, None, None, None, None, None,
1294 '--depth=files', wc
)
1295 svntest
.actions
.run_and_verify_svn(None, "Depth: +files|Path.+|URL.+|" \
1296 "Repository.+|Revision.+|Node Kind.+|" \
1297 "Schedule.+|Last.+|\n", [], "info", wc
)
1299 def status_in_depthy_wc(sbox
):
1300 "status -u at various depths in non-infinity wc"
1302 wc_empty
, ign_a
, ign_b
, wc
= set_up_depthy_working_copies(sbox
, empty
=True,
1305 iota_path
= os
.path
.join(wc
, 'iota')
1306 A_path
= os
.path
.join(wc
, 'A')
1307 mu_path
= os
.path
.join(wc
, 'A', 'mu')
1308 gamma_path
= os
.path
.join(wc
, 'A', 'D', 'gamma')
1310 # Make some changes in the depth-infinity wc, and commit them
1311 svntest
.actions
.run_and_verify_svn(None, None, [],
1312 'propset', 'foo', 'foo-val', wc
)
1313 svntest
.main
.file_write(iota_path
, "new text\n")
1314 svntest
.actions
.run_and_verify_svn(None, None, [],
1315 'propset', 'bar', 'bar-val', A_path
)
1316 svntest
.main
.file_write(mu_path
, "new text\n")
1317 svntest
.main
.file_write(gamma_path
, "new text\n")
1318 svntest
.actions
.run_and_verify_svn(None, None, [],
1319 'commit', '-m', '', wc
)
1322 "Status against revision: 2\n",
1326 " * 1 " + os
.path
.join('A', 'mu') + "\n",
1331 expected_output
= svntest
.verify
.UnorderedOutput(status
[:2])
1332 # The output should contain only the change on '.'.
1333 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1336 # Upgrade to depth-files.
1337 svntest
.actions
.run_and_verify_svn(None, None, [], 'up',
1338 '--depth', 'files', '-r1')
1339 # The output should contain only the changes on '.' and 'iota'.
1340 expected_output
= svntest
.verify
.UnorderedOutput(status
[:3])
1341 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1343 # Do a status -u at --depth empty.
1344 expected_output
= svntest
.verify
.UnorderedOutput(status
[:2])
1345 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1346 'st', '-u', '--depth', 'empty')
1348 # Upgrade to depth-immediates.
1349 svntest
.actions
.run_and_verify_svn(None, None, [], 'up',
1350 '--depth', 'immediates', '-r1')
1351 # The output should contain the changes on '.', 'A' and 'iota'.
1352 expected_output
= svntest
.verify
.UnorderedOutput(status
[:4])
1353 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1355 # Do a status -u at --depth files.
1356 expected_output
= svntest
.verify
.UnorderedOutput(status
[:3])
1357 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1358 'st', '-u', '--depth', 'files')
1360 # Upgrade A to depth-files.
1361 svntest
.actions
.run_and_verify_svn(None, None, [], 'up',
1362 '--depth', 'files', '-r1', 'A')
1363 # The output should contain everything but the change on
1364 # gamma (which does not exist in this working copy).
1365 expected_output
= svntest
.verify
.UnorderedOutput(status
)
1366 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1368 # Do a status -u at --depth immediates.
1369 expected_output
= svntest
.verify
.UnorderedOutput(status
[:4])
1370 svntest
.actions
.run_and_verify_svn(None, expected_output
, [],
1371 'st', '-u', '--depth', 'immediates')
1373 #----------------------------------------------------------------------
1376 def depthy_update_above_dir_to_be_deleted(sbox
):
1377 "'update -N' above a WC path deleted in repos HEAD"
1382 "immediates" : sbox
.clone_dependent(copy_wc
=True),
1383 "empty" : sbox
.clone_dependent(copy_wc
=True),
1387 svntest
.actions
.run_and_verify_svn(None, None, [],
1388 "delete", "-m", "Delete A.",
1389 sbox
.repo_url
+ "/A")
1391 def empty_output(wc_dir
):
1392 return svntest
.wc
.State(wc_dir
, { })
1394 def output_with_A(wc_dir
):
1395 expected_output
= empty_output(wc_dir
)
1396 expected_output
.add({
1397 "A" : Item(status
="D "),
1399 return expected_output
1401 initial_disk
= svntest
.main
.greek_state
.copy()
1402 disk_with_only_iota
= svntest
.wc
.State("", {
1403 "iota" : Item("This is the file 'iota'.\n"),
1406 def status_with_dot(wc_dir
):
1407 expected_status
= svntest
.actions
.get_virginal_state(wc_dir
, 1)
1408 expected_status
.tweak("", wc_rev
=2)
1409 return expected_status
1411 def status_with_iota(wc_dir
):
1412 expected_status
= status_with_dot(wc_dir
)
1413 expected_status
.tweak("iota", wc_rev
=2)
1414 return expected_status
1416 def status_with_only_iota(wc_dir
):
1417 return svntest
.wc
.State(wc_dir
, {
1418 "" : Item(status
=" ", wc_rev
=2),
1419 "iota" : Item(status
=" ", wc_rev
=2),
1422 expected_trees_for_depth
= {
1423 "files" : (empty_output
, initial_disk
, status_with_iota
),
1424 "immediates" : (output_with_A
, disk_with_only_iota
, status_with_only_iota
),
1425 "empty" : (empty_output
, initial_disk
, status_with_dot
),
1428 for depth
in sbox_for_depth
.keys():
1429 wc_dir
= sbox_for_depth
[depth
].wc_dir
1430 (expected_output_func
, expected_disk
, expected_status_func
) = \
1431 expected_trees_for_depth
[depth
]
1433 svntest
.actions
.run_and_verify_update(wc_dir
,
1434 expected_output_func(wc_dir
),
1436 expected_status_func(wc_dir
),
1437 None, None, None, None, None,
1439 "--depth=%s" % depth
, wc_dir
)
1442 #----------------------------------------------------------------------
1444 # list all tests here, starting with None:
1446 depth_empty_checkout
,
1447 depth_files_checkout
,
1448 nonrecursive_checkout
,
1449 depth_empty_update_bypass_single_file
,
1450 depth_immediates_get_top_file_mod_only
,
1452 depth_empty_with_file
,
1453 depth_empty_with_dir
,
1454 depth_immediates_bring_in_file
,
1455 depth_immediates_fill_in_dir
,
1456 depth_mixed_bring_in_dir
,
1457 depth_empty_unreceive_delete
,
1458 depth_immediates_unreceive_delete
,
1459 depth_immediates_receive_delete
,
1460 depth_update_to_more_depth
,
1461 depth_immediates_subdir_propset_1
,
1462 depth_immediates_subdir_propset_2
,
1463 commit_propmods_with_depth_empty
,
1465 commit_depth_immediates
,
1466 depth_immediates_receive_new_dir
,
1467 add_tree_with_depth_files
,
1469 status_in_depthy_wc
,
1470 depthy_update_above_dir_to_be_deleted
,
1473 if __name__
== "__main__":
1474 svntest
.main
.run_tests(test_list
)