In the command-line client, forbid
[svn.git] / subversion / tests / cmdline / depth_tests.py
blob5b299690dbfa9413f88ee98ffbf614eb4675d8d2
1 #!/usr/bin/env python
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 ######################################################################
21 # General modules
22 import os
24 # Our testing module
25 import svntest
26 from svntest import wc
28 # (abbreviation)
29 Skip = svntest.testcase.Skip
30 XFail = svntest.testcase.XFail
31 Item = wc.StateItem
33 # For errors setting up the depthy working copies.
34 class DepthSetupError(Exception):
35 def __init__ (self, args=None):
36 self.args = args
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
45 DepthSetupError."""
47 if not (infinity or empty or files or immediates):
48 raise DepthSetupError("At least one working copy depth must be passed.")
50 wc = None
51 if infinity:
52 sbox.build()
53 wc = sbox.wc_dir
54 else:
55 sbox.build(create_wc = False)
56 sbox.add_test_path(sbox.wc_dir, True)
58 wc_empty = None
59 if empty:
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)
67 wc_files = None
68 if files:
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)
76 wc_immediates = None
77 if immediates:
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
114 two tests."""
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,
157 infinity=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,
167 expected_output,
168 expected_status,
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,
177 expected_output,
178 expected_disk,
179 expected_status,
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,
204 expected_output,
205 expected_status,
206 None, None, None, None, None, wc)
208 # Update the depth-immediates wc, expecting to receive only the
209 # change to iota.
210 expected_output = svntest.wc.State(wc_immediates,
211 { 'iota' : Item(status='U ') })
212 expected_disk = svntest.wc.State('', { })
213 expected_disk.add(\
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,
223 expected_output,
224 expected_disk,
225 expected_status,
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,
234 empty=True)
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, [],
241 'up', wc_empty_iota)
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,
254 expected_output,
255 expected_status,
256 None, None, None, None, None,
257 wc_empty)
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,
264 infinity=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,
288 expected_output,
289 expected_status,
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,
299 expected_output,
300 expected_status,
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,
313 expected_output,
314 expected_disk,
315 expected_status,
316 None, None, None, None, None, False,
317 '-r2', wc_empty)
319 # Update the depth-empty wc all the way, expecting to receive the deletion
320 # of iota.
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,
327 expected_output,
328 expected_disk,
329 expected_status,
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,
338 infinity=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,
371 expected_output,
372 expected_disk,
373 expected_status,
374 None, None,
375 None, None, None, None,
376 A_path)
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,
385 expected_output,
386 expected_status,
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,
398 expected_output,
399 expected_disk,
400 expected_status,
401 None, None,
402 None, None, None, None,
403 A_path)
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,
412 expected_output,
413 expected_status,
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,
427 expected_output,
428 expected_disk,
429 expected_status,
430 None, None,
431 None, None, None, None,
432 A_path)
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,
442 immediates=True)
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,
461 expected_output,
462 expected_disk,
463 expected_status,
464 None, None, None,
465 None, None, None,
466 A_mu_path)
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,
483 expected_output,
484 expected_disk,
485 expected_status,
486 None, None, None,
487 None, None, None,
488 gamma_path)
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,
521 expected_output,
522 expected_disk,
523 expected_status,
524 None, None,
525 None, None, None, None,
526 '--depth', 'infinity',
527 A_path)
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,
554 expected_output,
555 expected_disk,
556 expected_status,
557 None, None,
558 None, None, None, None,
559 '--depth', 'files',
560 A_path)
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",
565 A_path)
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',
578 'A/D/H/omega')
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',
583 'A/D/H/omega')
584 svntest.actions.run_and_verify_update(wc_empty,
585 expected_output,
586 expected_disk,
587 expected_status,
588 None, None,
589 None, None, None, None,
590 '--depth', 'immediates',
591 B_path)
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",
596 B_path)
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',
606 'A/D/H/omega')
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',
611 'A/D/H/omega')
612 svntest.actions.run_and_verify_update(wc_empty,
613 expected_output,
614 expected_disk,
615 expected_status,
616 None, None,
617 None, None, None, None,
618 '--depth', 'empty',
619 C_path)
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",
624 C_path)
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,
632 infinity=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,
642 expected_output,
643 expected_status,
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,
652 expected_output,
653 expected_disk,
654 expected_status,
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,
665 immediates=True,
666 infinity=True)
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,
676 expected_output,
677 expected_status,
678 None, None, None, None, None, wc)
680 # Update the depth-immediates wc, expecting not to receive the deletion
681 # of A/mu.
682 expected_output = svntest.wc.State(wc_immed, { })
683 expected_disk = svntest.wc.State('', {
684 'iota' : Item(contents="This is the file 'iota'.\n"),
685 'A' : Item()
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,
693 expected_output,
694 expected_disk,
695 expected_status,
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,
705 immediates=True,
706 infinity=True)
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,
718 expected_output,
719 expected_status,
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,
734 expected_output,
735 expected_disk,
736 expected_status,
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',
750 A_path)
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,
766 expected_output,
767 expected_status,
768 None,
769 None, None,
770 None, None,
771 A_path)
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,
786 expected_output,
787 expected_disk,
788 expected_status,
789 None, None, None, None, None, 1)
791 #----------------------------------------------------------------------
792 def depth_immediates_subdir_propset_2(sbox):
793 "depth-immediates update receives subdir propset"
794 sbox.build()
795 wc_dir = sbox.wc_dir
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',
806 A_path)
807 # Commit.
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',
815 other_wc)
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)
823 os.chdir(wc_dir)
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('',
837 expected_output,
838 expected_disk,
839 expected_status,
840 None, None,
841 None, None, None, None,
842 '--depth', 'files')
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"),
858 'A' : Item(),
860 svntest.actions.run_and_verify_update('',
861 expected_output,
862 expected_disk,
863 expected_status,
864 None, None,
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"),
886 'A' : Item(),
887 'A/mu' : Item("This is the file 'mu'.\n"),
889 svntest.actions.run_and_verify_update('',
890 expected_output,
891 expected_disk,
892 expected_status,
893 None, None,
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('',
926 expected_output,
927 expected_disk,
928 expected_status,
929 None, None,
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 \
939 to depth-infinity")
941 def commit_propmods_with_depth_empty(sbox):
942 "commit property mods only, using --depth=empty"
943 sbox.build()
944 wc_dir = sbox.wc_dir
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(
971 wc_dir,
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,
988 expected_output,
989 expected_status,
990 None,
991 None, None,
992 None, None,
993 '--depth=empty',
994 wc_dir, D_path)
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,
1001 infinity=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)
1019 diff = [
1020 "\n",
1021 "Property changes on: .\n",
1022 "___________________________________________________________________\n",
1023 "Deleted: foo\n",
1024 " - foo-val\n",
1025 "\n",
1026 "Index: iota\n",
1027 "===================================================================\n",
1028 "--- iota\t(revision 2)\n",
1029 "+++ iota\t(working copy)\n",
1030 "@@ -1 +1 @@\n",
1031 "-new text\n",
1032 "+This is the file 'iota'.\n",
1033 "Property changes on: A\n",
1034 "___________________________________________________________________\n",
1035 "Deleted: bar\n",
1036 " - bar-val\n",
1037 "\n",
1038 "\n",
1039 "Index: A/mu\n",
1040 "===================================================================\n",
1041 "--- A/mu\t(revision 2)\n",
1042 "+++ A/mu\t(working copy)\n",
1043 "@@ -1 +1 @@\n",
1044 "-new text\n",
1045 "+This is the file 'mu'.\n" ]
1047 os.chdir(wc_empty)
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, [],
1052 'diff', '-rHEAD')
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, [],
1061 'diff', '-rHEAD')
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, [],
1074 'diff', '-rHEAD')
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, [],
1087 'diff', '-rHEAD')
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"
1095 sbox.build()
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:
1116 # M A/mu
1117 # M A/D/G/rho
1118 # M iota
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:
1133 # Sending A/D/G/rho
1134 # Sending iota
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,
1156 expected_output,
1157 expected_status,
1158 None,
1159 None, None,
1160 None, None,
1161 '--depth', 'immediates',
1162 wc_dir, G_path)
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,
1168 immediates=True,
1169 infinity=True)
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')
1175 os.mkdir(I_path)
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,
1190 expected_output,
1191 expected_status,
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"),
1201 'A' : Item(),
1202 'I' : Item(),
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,
1211 expected_output,
1212 expected_disk,
1213 expected_status,
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",
1219 other_I_path)
1221 def add_tree_with_depth_files(sbox):
1222 "add multi-subdir tree with --depth=files" # For issue #2931
1223 sbox.build()
1224 wc_dir = sbox.wc_dir
1225 new1_path = os.path.join(wc_dir, 'new1')
1226 new2_path = os.path.join(new1_path, 'new2')
1227 os.mkdir(new1_path)
1228 os.mkdir(new2_path)
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()
1252 try:
1253 os.chdir(wc)
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('',
1265 expected_output,
1266 expected_disk,
1267 expected_status,
1268 None, None, None, None, None, None,
1269 '--depth=files')
1270 svntest.actions.run_and_verify_svn(None, "Depth: +files|Path.+|URL.+|" \
1271 "Repository.+|Revision.+|Node Kind.+|" \
1272 "Schedule.+|Last.+|\n", [], "info")
1273 finally:
1274 os.chdir(saved_cwd)
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,
1290 expected_output,
1291 expected_disk,
1292 expected_status,
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,
1303 infinity=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)
1321 status = [
1322 "Status against revision: 2\n",
1323 " * 1 .\n",
1324 " * 1 iota\n",
1325 " * 1 A\n",
1326 " * 1 " + os.path.join('A', 'mu') + "\n",
1329 os.chdir(wc_empty)
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, [],
1334 'st', '-u')
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, [],
1342 'st', '-u')
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, [],
1354 'st', '-u')
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, [],
1367 'st', '-u')
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 #----------------------------------------------------------------------
1375 # Issue #3039.
1376 def depthy_update_above_dir_to_be_deleted(sbox):
1377 "'update -N' above a WC path deleted in repos HEAD"
1378 sbox.build()
1380 sbox_for_depth = {
1381 "files" : sbox,
1382 "immediates" : sbox.clone_dependent(copy_wc=True),
1383 "empty" : sbox.clone_dependent(copy_wc=True),
1386 output, err = \
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]
1432 #print depth
1433 svntest.actions.run_and_verify_update(wc_dir,
1434 expected_output_func(wc_dir),
1435 expected_disk,
1436 expected_status_func(wc_dir),
1437 None, None, None, None, None,
1438 False,
1439 "--depth=%s" % depth, wc_dir)
1442 #----------------------------------------------------------------------
1444 # list all tests here, starting with None:
1445 test_list = [ 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,
1451 depth_empty_commit,
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,
1464 diff_in_depthy_wc,
1465 commit_depth_immediates,
1466 depth_immediates_receive_new_dir,
1467 add_tree_with_depth_files,
1468 upgrade_from_above,
1469 status_in_depthy_wc,
1470 depthy_update_above_dir_to_be_deleted,
1473 if __name__ == "__main__":
1474 svntest.main.run_tests(test_list)
1475 # NOTREACHED
1478 ### End of file.