source: valtobtest/subversion-1.6.2/subversion/tests/cmdline/depth_tests.py @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

  • Property svn:executable set to *
File size: 102.3 KB
Line 
1#!/usr/bin/env python
2#
3#  depth_tests.py:  Testing that operations work as expected at
4#                   various depths (depth-empty, depth-files,
5#                   depth-immediates, depth-infinity).
6#
7#  Subversion is a tool for revision control.
8#  See http://subversion.tigris.org for more information.
9#
10# ====================================================================
11# Copyright (c) 2007 CollabNet.  All rights reserved.
12#
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.
18#
19######################################################################
20
21# General modules
22import os
23
24# Our testing module
25import svntest
26from svntest import wc
27
28# (abbreviation)
29Skip = svntest.testcase.Skip
30XFail = svntest.testcase.XFail
31Item = wc.StateItem
32
33# For errors setting up the depthy working copies.
34class DepthSetupError(Exception):
35  def __init__ (self, args=None):
36    self.args = args
37
38def 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."""
46
47  if not (infinity or empty or files or immediates):
48    raise DepthSetupError("At least one working copy depth must be passed.")
49
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)
57
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)
66
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)
75
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)
85
86  return wc_empty, wc_files, wc_immediates, wc
87
88def verify_depth(msg, depth, path="."):
89  """Verifies that PATH has depth DEPTH.  MSG is the failure message."""
90  if depth == "infinity":
91    # Check for absence of depth line.
92    exit_code, out, err = svntest.actions.run_and_verify_svn(None, None,
93                                                             [], "info", path)
94    for line in out:
95      if line.startswith("Depth:"):
96        raise svntest.failure(msg)
97  else:
98    svntest.actions.run_and_verify_svn_match_any(
99      msg, "^Depth: %s\n$" % depth, [], "info", path)
100
101#----------------------------------------------------------------------
102# Ensure that 'checkout --depth=empty' results in a depth-empty working copy.
103def depth_empty_checkout(sbox):
104  "depth-empty checkout"
105
106  wc_empty, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
107
108  if os.path.exists(os.path.join(wc_empty, "iota")):
109    raise svntest.Failure("depth-empty checkout created file 'iota'")
110
111  if os.path.exists(os.path.join(wc_empty, "A")):
112    raise svntest.Failure("depth-empty checkout created subdir 'A'")
113
114  verify_depth("Expected depth empty for top of WC, got some other depth",
115               "empty", wc_empty)
116
117
118# Helper for two test functions.
119def depth_files_same_as_nonrecursive(sbox, opt):
120  """Run a depth-files or non-recursive checkout, depending on whether
121  passed '-N' or '--depth=files' for OPT.  The two should get the same
122  result, hence this helper containing the common code between the
123  two tests."""
124
125  # This duplicates some code from set_up_depthy_working_copies(), but
126  # that's because it's abstracting out a different axis.
127
128  sbox.build(create_wc = False, read_only = True)
129  if os.path.exists(sbox.wc_dir):
130    svntest.main.safe_rmtree(sbox.wc_dir)
131
132  svntest.actions.run_and_verify_svn("Unexpected error during co %s" % opt,
133                                     svntest.verify.AnyOutput, [],
134                                     "co", opt, sbox.repo_url, sbox.wc_dir)
135
136  # Should create a depth-files top directory, so both iota and A
137  # should exist, and A should be empty and depth-empty.
138
139  if not os.path.exists(os.path.join(sbox.wc_dir, "iota")):
140    raise svntest.Failure("'checkout %s' failed to create file 'iota'" % opt)
141
142  if os.path.exists(os.path.join(sbox.wc_dir, "A")):
143    raise svntest.Failure("'checkout %s' unexpectedly created subdir 'A'" % opt)
144
145  verify_depth("Expected depth files for top of WC, got some other depth",
146               "files", sbox.wc_dir)
147
148
149def depth_files_checkout(sbox):
150  "depth-files checkout"
151  depth_files_same_as_nonrecursive(sbox, "--depth=files")
152
153
154def nonrecursive_checkout(sbox):
155  "non-recursive checkout equals depth-files"
156  depth_files_same_as_nonrecursive(sbox, "-N")
157
158
159#----------------------------------------------------------------------
160def depth_empty_update_bypass_single_file(sbox):
161  "update depth-empty wc shouldn't receive file mod"
162
163  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
164                                                            infinity=True)
165
166  iota_path = os.path.join(wc, 'iota')
167  svntest.main.file_append(iota_path, "new text\n")
168
169  # Commit in the "other" wc.
170  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Sending'), })
171  expected_status = svntest.actions.get_virginal_state(wc, 1)
172  expected_status.tweak('iota', wc_rev=2, status='  ')
173  svntest.actions.run_and_verify_commit(wc,
174                                        expected_output,
175                                        expected_status,
176                                        None, wc)
177
178  # Update the depth-empty wc, expecting not to receive the change to iota.
179  expected_output = svntest.wc.State(wc_empty, { })
180  expected_disk = svntest.wc.State('', { })
181  expected_status = svntest.wc.State(wc_empty, { '' : svntest.wc.StateItem() })
182  expected_status.tweak(contents=None, status='  ', wc_rev=2)
183  svntest.actions.run_and_verify_update(wc_empty,
184                                        expected_output,
185                                        expected_disk,
186                                        expected_status,
187                                        None, None, None, None, None)
188
189  # And the wc should still be depth-empty.
190  verify_depth(None, "empty", wc_empty)
191
192  # Even if we explicitly ask for a depth-infinity update, we still shouldn't
193  # get the change to iota.
194  svntest.actions.run_and_verify_update(wc_empty,
195                                        expected_output,
196                                        expected_disk,
197                                        expected_status,
198                                        None, None, None, None, None, False,
199                                        "--depth=infinity", wc_empty)
200
201  # And the wc should still be depth-empty.
202  verify_depth(None, "empty", wc_empty)
203
204
205#----------------------------------------------------------------------
206def depth_immediates_get_top_file_mod_only(sbox):
207  "update depth-immediates wc gets top file mod only"
208
209  ign_a, ign_b, wc_immediates, wc \
210         = set_up_depthy_working_copies(sbox, immediates=True, infinity=True)
211
212  iota_path = os.path.join(wc, 'iota')
213  svntest.main.file_append(iota_path, "new text in iota\n")
214  mu_path = os.path.join(wc, 'A', 'mu')
215  svntest.main.file_append(mu_path, "new text in mu\n")
216
217  # Commit in the "other" wc.
218  expected_output = svntest.wc.State(wc,
219                                     { 'iota' : Item(verb='Sending'),
220                                       'A/mu' : Item(verb='Sending'),
221                                       })
222  expected_status = svntest.actions.get_virginal_state(wc, 1)
223  expected_status.tweak('iota', wc_rev=2, status='  ')
224  expected_status.tweak('A/mu', wc_rev=2, status='  ')
225  svntest.actions.run_and_verify_commit(wc,
226                                        expected_output,
227                                        expected_status,
228                                        None, wc)
229
230  # Update the depth-immediates wc, expecting to receive only the
231  # change to iota.
232  expected_output = svntest.wc.State(wc_immediates,
233                                     { 'iota' : Item(status='U ') })
234  expected_disk = svntest.wc.State('', { })
235  expected_disk.add(\
236    {'iota' : Item(contents="This is the file 'iota'.\nnew text in iota\n"),
237     'A' : Item(contents=None) } )
238  expected_status = svntest.wc.State(wc_immediates,
239                                     { '' : svntest.wc.StateItem() })
240  expected_status.tweak(contents=None, status='  ', wc_rev=2)
241  expected_status.add(\
242    {'iota' : Item(status='  ', wc_rev=2),
243     'A' : Item(status='  ', wc_rev=2) } )
244  svntest.actions.run_and_verify_update(wc_immediates,
245                                        expected_output,
246                                        expected_disk,
247                                        expected_status,
248                                        None, None, None, None, None)
249  verify_depth(None, "immediates", wc_immediates)
250
251
252#----------------------------------------------------------------------
253def depth_empty_commit(sbox):
254  "commit a file from a depth-empty working copy"
255  # Bring iota into a depth-empty working copy, then commit a change to it.
256  wc_empty, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox,
257                                                               empty=True)
258
259  # Form the working path of iota
260  wc_empty_iota = os.path.join(wc_empty, 'iota')
261
262  # Update 'iota' in the depth-empty working copy and modify it
263  svntest.actions.run_and_verify_svn(None, None, [],
264                                     'up', wc_empty_iota)
265  svntest.main.file_write(wc_empty_iota, "iota modified")
266
267  # Commit the modified changes from a depth-empty working copy
268  expected_output = svntest.wc.State(wc_empty, {
269    'iota'        : Item(verb='Sending'),
270    })
271  expected_status = svntest.wc.State(wc_empty, { })
272  expected_status.add({
273    ''            : Item(status='  ', wc_rev=1),
274    'iota'        : Item(status='  ', wc_rev=2),
275    })
276  svntest.actions.run_and_verify_commit(wc_empty,
277                                        expected_output,
278                                        expected_status,
279                                        None,
280                                        wc_empty)
281
282#----------------------------------------------------------------------
283def depth_empty_with_file(sbox):
284  "act on a file in a depth-empty working copy"
285  # Run 'svn up iota' to bring iota permanently into the working copy.
286  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
287                                                            infinity=True)
288
289  iota_path = os.path.join(wc_empty, 'iota')
290  if os.path.exists(iota_path):
291    raise svntest.Failure("'%s' exists when it shouldn't" % iota_path)
292
293  # ### I'd love to do this using the recommended {expected_output,
294  # ### expected_status, expected_disk} method here, but after twenty
295  # ### minutes of trying to figure out how, I decided to compromise.
296
297  # Update iota by name, expecting to receive it.
298  svntest.actions.run_and_verify_svn(None, None, [], 'up', iota_path)
299
300  # Test that we did receive it.
301  if not os.path.exists(iota_path):
302    raise svntest.Failure("'%s' doesn't exist when it should" % iota_path)
303
304  # Commit a change to iota in the "other" wc.
305  other_iota_path = os.path.join(wc, 'iota')
306  svntest.main.file_append(other_iota_path, "new text\n")
307  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Sending'), })
308  expected_status = svntest.actions.get_virginal_state(wc, 1)
309  expected_status.tweak('iota', wc_rev=2, status='  ')
310  svntest.actions.run_and_verify_commit(wc,
311                                        expected_output,
312                                        expected_status,
313                                        None, wc)
314
315  # Delete iota in the "other" wc.
316  other_iota_path = os.path.join(wc, 'iota')
317  svntest.actions.run_and_verify_svn(None, None, [], 'rm', other_iota_path)
318  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Deleting'), })
319  expected_status = svntest.actions.get_virginal_state(wc, 1)
320  expected_status.remove('iota')
321  svntest.actions.run_and_verify_commit(wc,
322                                        expected_output,
323                                        expected_status,
324                                        None, wc)
325
326  # Update the depth-empty wc just a little, expecting to receive
327  # the change in iota.
328  expected_output = svntest.wc.State(\
329    wc_empty, { 'iota' : Item(status='U ') })
330  expected_disk = svntest.wc.State(\
331    '', { 'iota' : Item(contents="This is the file 'iota'.\nnew text\n") })
332  expected_status = svntest.wc.State(wc_empty,
333    { ''     : Item(status='  ', wc_rev=2),
334      'iota' : Item(status='  ', wc_rev=2),})
335  svntest.actions.run_and_verify_update(wc_empty,
336                                        expected_output,
337                                        expected_disk,
338                                        expected_status,
339                                        None, None, None, None, None, False,
340                                        '-r2', wc_empty)
341
342  # Update the depth-empty wc all the way, expecting to receive the deletion
343  # of iota.
344  expected_output = svntest.wc.State(\
345    wc_empty, { 'iota' : Item(status='D ') })
346  expected_disk = svntest.wc.State('', { })
347  expected_status = svntest.wc.State(\
348    wc_empty, { '' : Item(status='  ', wc_rev=3) })
349  svntest.actions.run_and_verify_update(wc_empty,
350                                        expected_output,
351                                        expected_disk,
352                                        expected_status,
353                                        None, None, None, None, None)
354
355
356#----------------------------------------------------------------------
357def depth_empty_with_dir(sbox):
358  "bring a dir into a depth-empty working copy"
359  # Run 'svn up A' to bring A permanently into the working copy.
360  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
361                                                            infinity=True)
362
363  A_path = os.path.join(wc_empty, 'A')
364  other_mu_path = os.path.join(wc, 'A', 'mu')
365
366  # We expect A to be added at depth infinity, so a normal 'svn up A'
367  # should be sufficient to add all descendants.
368  expected_output = svntest.wc.State(wc_empty, {
369    'A'              : Item(status='A '),
370    'A/mu'           : Item(status='A '),
371    'A/B'            : Item(status='A '),
372    'A/B/lambda'     : Item(status='A '),
373    'A/B/E'          : Item(status='A '),
374    'A/B/E/alpha'    : Item(status='A '),
375    'A/B/E/beta'     : Item(status='A '),
376    'A/B/F'          : Item(status='A '),
377    'A/C'            : Item(status='A '),
378    'A/D'            : Item(status='A '),
379    'A/D/gamma'      : Item(status='A '),
380    'A/D/G'          : Item(status='A '),
381    'A/D/G/pi'       : Item(status='A '),
382    'A/D/G/rho'      : Item(status='A '),
383    'A/D/G/tau'      : Item(status='A '),
384    'A/D/H'          : Item(status='A '),
385    'A/D/H/chi'      : Item(status='A '),
386    'A/D/H/psi'      : Item(status='A '),
387    'A/D/H/omega'    : Item(status='A ')
388    })
389  expected_disk = svntest.main.greek_state.copy()
390  expected_disk.remove('iota')
391  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
392  expected_status.remove('iota')
393  svntest.actions.run_and_verify_update(wc_empty,
394                                        expected_output,
395                                        expected_disk,
396                                        expected_status,
397                                        None, None,
398                                        None, None, None, None,
399                                        A_path)
400
401  # Commit a change to A/mu in the "other" wc.
402  svntest.main.file_write(other_mu_path, "new text\n")
403  expected_output = svntest.wc.State(\
404    wc, { 'A/mu' : Item(verb='Sending'), })
405  expected_status = svntest.actions.get_virginal_state(wc, 1)
406  expected_status.tweak('A/mu', wc_rev=2, status='  ')
407  svntest.actions.run_and_verify_commit(wc,
408                                        expected_output,
409                                        expected_status,
410                                        None, wc)
411
412  # Update "A" by name in wc_empty, expect to receive the change to A/mu.
413  expected_output = svntest.wc.State(wc_empty, { 'A/mu' : Item(status='U ') })
414  expected_disk = svntest.main.greek_state.copy()
415  expected_disk.remove('iota')
416  expected_disk.tweak('A/mu', contents='new text\n')
417  expected_status = svntest.actions.get_virginal_state(wc_empty, 2)
418  expected_status.remove('iota')
419  expected_status.tweak('', wc_rev=1)
420  svntest.actions.run_and_verify_update(wc_empty,
421                                        expected_output,
422                                        expected_disk,
423                                        expected_status,
424                                        None, None,
425                                        None, None, None, None,
426                                        A_path)
427
428  # Commit the deletion of A/mu from the "other" wc.
429  svntest.main.file_write(other_mu_path, "new text\n")
430  svntest.actions.run_and_verify_svn(None, None, [], 'rm', other_mu_path)
431  expected_output = svntest.wc.State(wc, { 'A/mu' : Item(verb='Deleting'), })
432  expected_status = svntest.actions.get_virginal_state(wc, 1)
433  expected_status.remove('A/mu')
434  svntest.actions.run_and_verify_commit(wc,
435                                        expected_output,
436                                        expected_status,
437                                        None, wc)
438
439
440  # Update "A" by name in wc_empty, expect to A/mu to disappear.
441  expected_output = svntest.wc.State(wc_empty, { 'A/mu' : Item(status='D ') })
442  expected_disk = svntest.main.greek_state.copy()
443  expected_disk.remove('iota')
444  expected_disk.remove('A/mu')
445  expected_status = svntest.actions.get_virginal_state(wc_empty, 3)
446  expected_status.remove('iota')
447  expected_status.remove('A/mu')
448  expected_status.tweak('', wc_rev=1)
449  svntest.actions.run_and_verify_update(wc_empty,
450                                        expected_output,
451                                        expected_disk,
452                                        expected_status,
453                                        None, None,
454                                        None, None, None, None,
455                                        A_path)
456
457
458
459#----------------------------------------------------------------------
460def depth_immediates_bring_in_file(sbox):
461  "bring a file into a depth-immediates working copy"
462
463  # Create an immediates working copy and form the paths
464  ign_a, ign_b, wc_imm, wc = set_up_depthy_working_copies(sbox,
465                                                          immediates=True)
466  A_mu_path = os.path.join(wc_imm, 'A', 'mu')
467  gamma_path = os.path.join(wc_imm, 'A', 'D', 'gamma')
468
469  # Run 'svn up A/mu' to bring A/mu permanently into the working copy.
470  expected_output = svntest.wc.State(wc_imm, {
471    'A/mu'           : Item(status='A '),
472    })
473  expected_disk = svntest.main.greek_state.copy()
474  expected_disk.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
475                       'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
476                       'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
477                       'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
478  expected_status = svntest.actions.get_virginal_state(wc_imm, 1)
479  expected_status.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
480                       'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
481                       'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
482                       'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
483  svntest.actions.run_and_verify_update(wc_imm,
484                                        expected_output,
485                                        expected_disk,
486                                        expected_status,
487                                        None, None, None,
488                                        None, None, None,
489                                        A_mu_path)
490
491  # Run 'svn up A/D/gamma' to test the edge case 'Skipped'.
492  expected_output = svntest.wc.State(wc_imm, {
493    'A/D/gamma'   : Item(verb='Skipped'),
494    })
495  expected_disk = svntest.main.greek_state.copy()
496  expected_disk.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
497                       'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
498                       'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
499                       'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
500  expected_status = svntest.actions.get_virginal_state(wc_imm, 1)
501  expected_status.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
502                       'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
503                       'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
504                       'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
505  svntest.actions.run_and_verify_update(wc_imm,
506                                        expected_output,
507                                        expected_disk,
508                                        expected_status,
509                                        None, None, None,
510                                        None, None, None,
511                                        gamma_path)
512
513#----------------------------------------------------------------------
514def depth_immediates_fill_in_dir(sbox):
515  "bring a dir into a depth-immediates working copy"
516
517  # Run 'svn up A --set-depth=infinity' to fill in A as a
518  # depth-infinity subdir.
519  ign_a, ign_b, wc_immediates, wc \
520                        = set_up_depthy_working_copies(sbox, immediates=True)
521  A_path = os.path.join(wc_immediates, 'A')
522  expected_output = svntest.wc.State(wc_immediates, {
523    'A/mu'           : Item(status='A '),
524    'A/B'            : Item(status='A '),
525    'A/B/lambda'     : Item(status='A '),
526    'A/B/E'          : Item(status='A '),
527    'A/B/E/alpha'    : Item(status='A '),
528    'A/B/E/beta'     : Item(status='A '),
529    'A/B/F'          : Item(status='A '),
530    'A/C'            : Item(status='A '),
531    'A/D'            : Item(status='A '),
532    'A/D/gamma'      : Item(status='A '),
533    'A/D/G'          : Item(status='A '),
534    'A/D/G/pi'       : Item(status='A '),
535    'A/D/G/rho'      : Item(status='A '),
536    'A/D/G/tau'      : Item(status='A '),
537    'A/D/H'          : Item(status='A '),
538    'A/D/H/chi'      : Item(status='A '),
539    'A/D/H/psi'      : Item(status='A '),
540    'A/D/H/omega'    : Item(status='A ')
541    })
542  expected_disk = svntest.main.greek_state.copy()
543  expected_status = svntest.actions.get_virginal_state(wc_immediates, 1)
544  svntest.actions.run_and_verify_update(wc_immediates,
545                                        expected_output,
546                                        expected_disk,
547                                        expected_status,
548                                        None, None,
549                                        None, None, None, None,
550                                        '--set-depth', 'infinity',
551                                        A_path)
552
553#----------------------------------------------------------------------
554def depth_mixed_bring_in_dir(sbox):
555  "bring a dir into a mixed-depth working copy"
556
557  # Run 'svn up --set-depth=immediates A' in a depth-empty working copy.
558  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True)
559  A_path = os.path.join(wc_empty, 'A')
560  B_path = os.path.join(wc_empty, 'A', 'B')
561  C_path = os.path.join(wc_empty, 'A', 'C')
562
563  expected_output = svntest.wc.State(wc_empty, {
564    'A'              : Item(status='A '),
565    'A/mu'           : Item(status='A '),
566    })
567  expected_disk = svntest.main.greek_state.copy()
568  expected_disk.remove('iota', 'A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
569                       'A/B/E/beta', 'A/B/F', 'A/C', 'A/D', 'A/D/gamma',
570                       'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
571                       'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
572  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
573  expected_status.remove('iota', 'A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
574                         'A/B/E/beta', 'A/B/F', 'A/C', 'A/D', 'A/D/gamma',
575                         'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
576                         'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
577  svntest.actions.run_and_verify_update(wc_empty,
578                                        expected_output,
579                                        expected_disk,
580                                        expected_status,
581                                        None, None,
582                                        None, None, None, None,
583                                        '--set-depth', 'files',
584                                        A_path)
585  # Check that A was added at depth=files.
586  verify_depth(None, "files", A_path)
587
588  # Now, bring in A/B at depth-immediates.
589  expected_output = svntest.wc.State(wc_empty, {
590    'A/B'            : Item(status='A '),
591    'A/B/lambda'     : Item(status='A '),
592    'A/B/E'          : Item(status='A '),
593    'A/B/F'          : Item(status='A '),
594    })
595  expected_disk = svntest.main.greek_state.copy()
596  expected_disk.remove('iota', 'A/B/E/alpha', 'A/B/E/beta', 'A/C',
597                       'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
598                       'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
599                       'A/D/H/omega')
600  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
601  expected_status.remove('iota', 'A/B/E/alpha', 'A/B/E/beta', 'A/C',
602                         'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
603                         'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
604                         'A/D/H/omega')
605  svntest.actions.run_and_verify_update(wc_empty,
606                                        expected_output,
607                                        expected_disk,
608                                        expected_status,
609                                        None, None,
610                                        None, None, None, None,
611                                        '--set-depth', 'immediates',
612                                        B_path)
613  # Check that A/B was added at depth=immediates.
614  verify_depth(None, "immediates", B_path)
615
616  # Now, bring in A/C at depth-empty.
617  expected_output = svntest.wc.State(wc_empty, {
618    'A/C'            : Item(status='A '),
619    })
620  expected_disk = svntest.main.greek_state.copy()
621  expected_disk.remove('iota', 'A/B/E/alpha', 'A/B/E/beta',
622                       'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
623                       'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
624                       'A/D/H/omega')
625  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
626  expected_status.remove('iota', 'A/B/E/alpha', 'A/B/E/beta',
627                         'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
628                         'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
629                         'A/D/H/omega')
630  svntest.actions.run_and_verify_update(wc_empty,
631                                        expected_output,
632                                        expected_disk,
633                                        expected_status,
634                                        None, None,
635                                        None, None, None, None,
636                                        '--set-depth', 'empty',
637                                        C_path)
638  # Check that A/C was added at depth=empty.
639  verify_depth(None, "empty", C_path)
640
641#----------------------------------------------------------------------
642def depth_empty_unreceive_delete(sbox):
643  "depth-empty working copy ignores a deletion"
644  # Check out a depth-empty greek tree to wc1.  In wc2, delete iota and
645  # commit.  Update wc1; should not receive the delete.
646  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
647                                                            infinity=True)
648
649  iota_path = os.path.join(wc, 'iota')
650
651  # Commit in the "other" wc.
652  svntest.actions.run_and_verify_svn(None, None, [], 'rm', iota_path)
653  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Deleting'), })
654  expected_status = svntest.actions.get_virginal_state(wc, 1)
655  expected_status.remove('iota')
656  svntest.actions.run_and_verify_commit(wc,
657                                        expected_output,
658                                        expected_status,
659                                        None, wc)
660
661  # Update the depth-empty wc, expecting not to receive the deletion of iota.
662  expected_output = svntest.wc.State(wc_empty, { })
663  expected_disk = svntest.wc.State('', { })
664  expected_status = svntest.wc.State(wc_empty, { '' : svntest.wc.StateItem() })
665  expected_status.tweak(contents=None, status='  ', wc_rev=2)
666  svntest.actions.run_and_verify_update(wc_empty,
667                                        expected_output,
668                                        expected_disk,
669                                        expected_status,
670                                        None, None, None, None, None)
671
672
673#----------------------------------------------------------------------
674def depth_immediates_unreceive_delete(sbox):
675  "depth-immediates working copy ignores a deletion"
676  # Check out a depth-immediates greek tree to wc1.  In wc2, delete
677  # A/mu and commit.  Update wc1; should not receive the delete.
678
679  ign_a, ign_b, wc_immed, wc = set_up_depthy_working_copies(sbox,
680                                                            immediates=True,
681                                                            infinity=True)
682
683  mu_path = os.path.join(wc, 'A', 'mu')
684
685  # Commit in the "other" wc.
686  svntest.actions.run_and_verify_svn(None, None, [], 'rm', mu_path)
687  expected_output = svntest.wc.State(wc, { 'A/mu' : Item(verb='Deleting'), })
688  expected_status = svntest.actions.get_virginal_state(wc, 1)
689  expected_status.remove('A/mu')
690  svntest.actions.run_and_verify_commit(wc,
691                                        expected_output,
692                                        expected_status,
693                                        None, wc)
694
695  # Update the depth-immediates wc, expecting not to receive the deletion
696  # of A/mu.
697  expected_output = svntest.wc.State(wc_immed, { })
698  expected_disk = svntest.wc.State('', {
699    'iota' : Item(contents="This is the file 'iota'.\n"),
700    'A' : Item()
701    })
702  expected_status = svntest.wc.State(wc_immed, {
703    '' : Item(status='  ', wc_rev=2),
704    'iota' : Item(status='  ', wc_rev=2),
705    'A' : Item(status='  ', wc_rev=2)
706    })
707  svntest.actions.run_and_verify_update(wc_immed,
708                                        expected_output,
709                                        expected_disk,
710                                        expected_status,
711                                        None, None, None, None, None)
712
713#----------------------------------------------------------------------
714def depth_immediates_receive_delete(sbox):
715  "depth-immediates working copy receives a deletion"
716  # Check out a depth-immediates greek tree to wc1.  In wc2, delete A and
717  # commit.  Update wc1  should receive the delete.
718
719  ign_a, ign_b, wc_immed, wc = set_up_depthy_working_copies(sbox,
720                                                            immediates=True,
721                                                            infinity=True)
722
723  A_path = os.path.join(wc, 'A')
724
725  # Commit in the "other" wc.
726  svntest.actions.run_and_verify_svn(None, None, [], 'rm', A_path)
727  expected_output = svntest.wc.State(wc, { 'A' : Item(verb='Deleting'), })
728  expected_status = svntest.wc.State(wc, {
729    '' : Item(status='  ', wc_rev=1),
730    'iota' : Item(status='  ', wc_rev=1),
731    })
732  svntest.actions.run_and_verify_commit(wc,
733                                        expected_output,
734                                        expected_status,
735                                        None, wc)
736
737  # Update the depth-immediates wc, expecting to receive the deletion of A.
738  expected_output = svntest.wc.State(wc_immed, {
739    'A'    : Item(status='D ')
740    })
741  expected_disk = svntest.wc.State('', {
742    'iota' : Item(contents="This is the file 'iota'.\n"),
743    })
744  expected_status = svntest.wc.State(wc_immed, {
745    ''     : Item(status='  ', wc_rev=2),
746    'iota' : Item(status='  ', wc_rev=2)
747    })
748  svntest.actions.run_and_verify_update(wc_immed,
749                                        expected_output,
750                                        expected_disk,
751                                        expected_status,
752                                        None, None, None, None, None)
753
754#----------------------------------------------------------------------
755def depth_immediates_subdir_propset_1(sbox):
756  "depth-immediates commit subdir propset, update"
757  ign_a, ign_b, wc_immediates, ign_c \
758         = set_up_depthy_working_copies(sbox, immediates=True)
759
760  A_path = os.path.join(wc_immediates, 'A')
761
762  # Set a property on an immediate subdirectory of the working copy.
763  svntest.actions.run_and_verify_svn(None, None, [],
764                                     'pset', 'foo', 'bar',
765                                     A_path)
766
767  # Create expected output tree.
768  expected_output = svntest.wc.State(wc_immediates, {
769    'A' : Item(verb='Sending'),
770    })
771
772  # Create expected status tree.
773  expected_status = svntest.wc.State(wc_immediates, {
774    '' : Item(status='  ', wc_rev=1),
775    'iota' : Item(status='  ', wc_rev=1),
776    'A' : Item(status='  ', wc_rev=2)
777    })
778
779  # Commit wc_immediates/A.
780  svntest.actions.run_and_verify_commit(wc_immediates,
781                                        expected_output,
782                                        expected_status,
783                                        None,
784                                        A_path)
785
786  # Create expected output tree for the update.
787  expected_output = svntest.wc.State(wc_immediates, { })
788
789  # Create expected disk tree.
790  expected_disk = svntest.wc.State('', {
791    'iota' : Item(contents="This is the file 'iota'.\n"),
792    'A' : Item(contents=None, props={'foo' : 'bar'}),
793    })
794
795  expected_status.tweak(contents=None, status='  ', wc_rev=2)
796
797  # Update the depth-immediates wc.
798  svntest.actions.run_and_verify_update(wc_immediates,
799                                        expected_output,
800                                        expected_disk,
801                                        expected_status,
802                                        None, None, None, None, None, 1)
803
804#----------------------------------------------------------------------
805def depth_immediates_subdir_propset_2(sbox):
806  "depth-immediates update receives subdir propset"
807  sbox.build()
808  wc_dir = sbox.wc_dir
809
810  # Make the other working copy.
811  other_wc = sbox.add_wc_path('other')
812  svntest.actions.duplicate_dir(wc_dir, other_wc)
813
814  A_path = os.path.join(wc_dir, 'A')
815
816  # Set a property on an immediate subdirectory of the working copy.
817  svntest.actions.run_and_verify_svn(None, None, [],
818                                     'pset', 'foo', 'bar',
819                                     A_path)
820  # Commit.
821  svntest.actions.run_and_verify_svn(None, None, [],
822                                     'commit', '-m', 'logmsg', A_path)
823
824  # Update at depth=immediates in the other wc, expecting to see no errors.
825  svntest.actions.run_and_verify_svn("Output on stderr where none expected",
826                                     svntest.verify.AnyOutput, [],
827                                     'update', '--depth', 'immediates',
828                                     other_wc)
829
830#----------------------------------------------------------------------
831def depth_update_to_more_depth(sbox):
832  "gradually update an empty wc to depth=infinity"
833
834  wc_dir, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
835
836  os.chdir(wc_dir)
837
838  # Run 'svn up --set-depth=files' in a depth-empty working copy.
839  expected_output = svntest.wc.State('', {
840    'iota'              : Item(status='A '),
841    })
842  expected_status = svntest.wc.State('', {
843    '' : Item(status='  ', wc_rev=1),
844    'iota' : Item(status='  ', wc_rev=1),
845    })
846  expected_disk = svntest.wc.State('', {
847    'iota' : Item("This is the file 'iota'.\n"),
848    })
849  svntest.actions.run_and_verify_update('',
850                                        expected_output,
851                                        expected_disk,
852                                        expected_status,
853                                        None, None,
854                                        None, None, None, None,
855                                        '--set-depth', 'files')
856  verify_depth(None, "files")
857
858  # Run 'svn up --set-depth=immediates' in the now depth-files working copy.
859  expected_output = svntest.wc.State('', {
860    'A'              : Item(status='A '),
861    })
862  expected_status = svntest.wc.State('', {
863    '' : Item(status='  ', wc_rev=1),
864    'iota' : Item(status='  ', wc_rev=1),
865    'A' : Item(status='  ', wc_rev=1),
866    })
867  expected_disk = svntest.wc.State('', {
868    'iota' : Item("This is the file 'iota'.\n"),
869    'A'    : Item(),
870    })
871  svntest.actions.run_and_verify_update('',
872                                        expected_output,
873                                        expected_disk,
874                                        expected_status,
875                                        None, None,
876                                        None, None, None, None,
877                                        '--set-depth', 'immediates')
878  verify_depth(None, "immediates")
879  verify_depth(None, "empty", "A")
880
881  # Upgrade 'A' to depth-files.
882  expected_output = svntest.wc.State('', {
883    'A/mu'           : Item(status='A '),
884    })
885  expected_status = svntest.wc.State('', {
886    '' : Item(status='  ', wc_rev=1),
887    'iota' : Item(status='  ', wc_rev=1),
888    'A' : Item(status='  ', wc_rev=1),
889    'A/mu' : Item(status='  ', wc_rev=1),
890    })
891  expected_disk = svntest.wc.State('', {
892    'iota' : Item("This is the file 'iota'.\n"),
893    'A'    : Item(),
894    'A/mu' : Item("This is the file 'mu'.\n"),
895    })
896  svntest.actions.run_and_verify_update('',
897                                        expected_output,
898                                        expected_disk,
899                                        expected_status,
900                                        None, None,
901                                        None, None, None, None,
902                                        '--set-depth', 'files', 'A')
903  verify_depth(None, "immediates")
904  verify_depth(None, "files", "A")
905
906  # Run 'svn up --set-depth=infinity' in the working copy.
907  expected_output = svntest.wc.State('', {
908    'A/B'            : Item(status='A '),
909    'A/B/lambda'     : Item(status='A '),
910    'A/B/E'          : Item(status='A '),
911    'A/B/E/alpha'    : Item(status='A '),
912    'A/B/E/beta'     : Item(status='A '),
913    'A/B/F'          : Item(status='A '),
914    'A/C'            : Item(status='A '),
915    'A/D'            : Item(status='A '),
916    'A/D/gamma'      : Item(status='A '),
917    'A/D/G'          : Item(status='A '),
918    'A/D/G/pi'       : Item(status='A '),
919    'A/D/G/rho'      : Item(status='A '),
920    'A/D/G/tau'      : Item(status='A '),
921    'A/D/H'          : Item(status='A '),
922    'A/D/H/chi'      : Item(status='A '),
923    'A/D/H/psi'      : Item(status='A '),
924    'A/D/H/omega'    : Item(status='A ')
925    })
926  expected_disk = svntest.main.greek_state.copy()
927  expected_status = svntest.actions.get_virginal_state('', 1)
928  svntest.actions.run_and_verify_update('',
929                                        expected_output,
930                                        expected_disk,
931                                        expected_status,
932                                        None, None,
933                                        None, None, None, None,
934                                        '--set-depth', 'infinity')
935  verify_depth("Non-infinity depth detected after an upgrade to depth-infinity",
936               "infinity")
937  verify_depth("Non-infinity depth detected after an upgrade to depth-infinity",
938               "infinity", "A")
939
940def commit_propmods_with_depth_empty_helper(sbox, depth_arg):
941  """Helper for commit_propmods_with_depth_empty().
942  DEPTH_ARG should be either '--depth=empty' or '-N'."""
943
944  sbox.build()
945  wc_dir = sbox.wc_dir
946
947  iota_path = os.path.join(wc_dir, 'iota')
948  A_path = os.path.join(wc_dir, 'A')
949  D_path = os.path.join(A_path, 'D')
950  gamma_path = os.path.join(D_path, 'gamma')
951  G_path = os.path.join(D_path, 'G')
952  pi_path = os.path.join(G_path, 'pi')
953  H_path = os.path.join(D_path, 'H')
954  chi_path = os.path.join(H_path, 'chi')
955
956  # Set some properties, modify some files.
957  svntest.actions.run_and_verify_svn(None, None, [],
958                                     'propset', 'foo', 'foo-val', wc_dir)
959  svntest.actions.run_and_verify_svn(None, None, [],
960                                     'propset', 'bar', 'bar-val', D_path)
961  svntest.actions.run_and_verify_svn(None, None, [],
962                                     'propset', 'baz', 'baz-val', G_path)
963  svntest.actions.run_and_verify_svn(None, None, [],
964                                     'propset', 'qux', 'qux-val', H_path)
965  svntest.main.file_append(iota_path, "new iota\n")
966  svntest.main.file_append(gamma_path, "new gamma\n")
967  svntest.main.file_append(pi_path, "new pi\n")
968  svntest.main.file_append(chi_path, "new chi\n")
969
970  # The only things that should be committed are two of the propsets.
971  expected_output = svntest.wc.State(
972    wc_dir,
973    { ''    : Item(verb='Sending'),
974      'A/D' : Item(verb='Sending'), }
975    )
976  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
977  # Expect the two propsets to be committed:
978  expected_status.tweak('', status='  ', wc_rev=2)
979  expected_status.tweak('A/D', status='  ', wc_rev=2)
980  # Expect every other change to remain uncommitted:
981  expected_status.tweak('iota', status='M ', wc_rev=1)
982  expected_status.tweak('A/D/G', status=' M', wc_rev=1)
983  expected_status.tweak('A/D/H', status=' M', wc_rev=1)
984  expected_status.tweak('A/D/gamma', status='M ', wc_rev=1)
985  expected_status.tweak('A/D/G/pi', status='M ', wc_rev=1)
986  expected_status.tweak('A/D/H/chi', status='M ', wc_rev=1)
987
988  svntest.actions.run_and_verify_commit(wc_dir,
989                                        expected_output,
990                                        expected_status,
991                                        None,
992                                        depth_arg,
993                                        wc_dir, D_path)
994
995# See also commit_tests 26: commit_nonrecursive
996def commit_propmods_with_depth_empty(sbox):
997  "commit property mods only, using --depth=empty"
998
999  sbox2 = sbox.clone_dependent()
1000
1001  # Run once with '-N' and once with '--depth=empty' to make sure they
1002  # function identically.
1003  commit_propmods_with_depth_empty_helper(sbox, '-N')
1004  commit_propmods_with_depth_empty_helper(sbox2, '--depth=empty')
1005
1006# Test for issue #2845.
1007def diff_in_depthy_wc(sbox):
1008  "diff at various depths in non-infinity wc"
1009
1010  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
1011                                                            infinity=True)
1012
1013  iota_path = os.path.join(wc, 'iota')
1014  A_path = os.path.join(wc, 'A')
1015  mu_path = os.path.join(wc, 'A', 'mu')
1016  gamma_path = os.path.join(wc, 'A', 'D', 'gamma')
1017
1018  # Make some changes in the depth-infinity wc, and commit them
1019  svntest.actions.run_and_verify_svn(None, None, [],
1020                                     'propset', 'foo', 'foo-val', wc)
1021  svntest.main.file_write(iota_path, "new text\n")
1022  svntest.actions.run_and_verify_svn(None, None, [],
1023                                     'propset', 'bar', 'bar-val', A_path)
1024  svntest.main.file_write(mu_path, "new text\n")
1025  svntest.main.file_write(gamma_path, "new text\n")
1026  svntest.actions.run_and_verify_svn(None, None, [],
1027                                     'commit', '-m', '', wc)
1028
1029  diff = [
1030    "\n",
1031    "Property changes on: .\n",
1032    "___________________________________________________________________\n",
1033    "Deleted: foo\n",
1034    "   - foo-val\n",
1035    "\n",
1036    "Index: iota\n",
1037    "===================================================================\n",
1038    "--- iota\t(revision 2)\n",
1039    "+++ iota\t(working copy)\n",
1040    "@@ -1 +1 @@\n",
1041    "-new text\n",
1042    "+This is the file 'iota'.\n",
1043    "Property changes on: A\n",
1044    "___________________________________________________________________\n",
1045    "Deleted: bar\n",
1046    "   - bar-val\n",
1047    "\n",
1048    "\n",
1049    "Index: A/mu\n",
1050    "===================================================================\n",
1051    "--- A/mu\t(revision 2)\n",
1052    "+++ A/mu\t(working copy)\n",
1053    "@@ -1 +1 @@\n",
1054    "-new text\n",
1055    "+This is the file 'mu'.\n" ]
1056
1057  os.chdir(wc_empty)
1058
1059  expected_output = svntest.verify.UnorderedOutput(diff[:6])
1060  # The diff should contain only the propchange on '.'
1061  svntest.actions.run_and_verify_svn(None, expected_output, [],
1062                                     'diff', '-rHEAD')
1063
1064  # Upgrade to depth-files.
1065  svntest.actions.run_and_verify_svn(None, None, [], 'up',
1066                                     '--set-depth', 'files', '-r1')
1067  # The diff should contain only the propchange on '.' and the
1068  # contents change on iota.
1069  expected_output = svntest.verify.UnorderedOutput(diff[:13])
1070  svntest.actions.run_and_verify_svn(None, expected_output, [],
1071                                     'diff', '-rHEAD')
1072  # Do a diff at --depth empty.
1073  expected_output = svntest.verify.UnorderedOutput(diff[:6])
1074  svntest.actions.run_and_verify_svn(None, expected_output, [],
1075                                     'diff', '--depth', 'empty', '-rHEAD')
1076
1077  # Upgrade to depth-immediates.
1078  svntest.actions.run_and_verify_svn(None, None, [], 'up',
1079                                     '--set-depth', 'immediates', '-r1')
1080  # The diff should contain the propchanges on '.' and 'A' and the
1081  # contents change on iota.
1082  expected_output = svntest.verify.UnorderedOutput(diff[:19])
1083  svntest.actions.run_and_verify_svn(None, expected_output, [],
1084                                    'diff', '-rHEAD')
1085  # Do a diff at --depth files.
1086  expected_output = svntest.verify.UnorderedOutput(diff[:13])
1087  svntest.actions.run_and_verify_svn(None, expected_output, [],
1088                                     'diff', '--depth', 'files', '-rHEAD')
1089
1090  # Upgrade A to depth-files.
1091  svntest.actions.run_and_verify_svn(None, None, [], 'up',
1092                                     '--set-depth', 'files', '-r1', 'A')
1093  # The diff should contain everything but the contents change on
1094  # gamma (which does not exist in this working copy).
1095  expected_output = svntest.verify.UnorderedOutput(diff)
1096  svntest.actions.run_and_verify_svn(None, expected_output, [],
1097                                     'diff', '-rHEAD')
1098  # Do a diff at --depth immediates.
1099  expected_output = svntest.verify.UnorderedOutput(diff[:19])
1100  svntest.actions.run_and_verify_svn(None, expected_output, [],
1101                                    'diff', '--depth', 'immediates', '-rHEAD')
1102
1103def commit_depth_immediates(sbox):
1104  "commit some files with --depth=immediates"
1105  sbox.build()
1106  wc_dir = sbox.wc_dir
1107
1108  # Test the fix for some bugs Mike Pilato reported here:
1109  #
1110  #    http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=128509
1111  #    From: "C. Michael Pilato" <cmpilato@collab.net>
1112  #    To: Karl Fogel <kfogel@red-bean.com>
1113  #    CC: dev@subversion.tigris.org
1114  #    References: <87d4yzcrro.fsf@red-bean.com>
1115  #    Subject: Re: [PATCH] Make 'svn commit --depth=foo' work.
1116  #    Message-ID: <46968831.2070906@collab.net>
1117  #    Date: Thu, 12 Jul 2007 15:59:45 -0400
1118  #
1119  # See also http://subversion.tigris.org/issues/show_bug.cgi?id=2882.
1120  #
1121  # Outline of the test:
1122  # ====================
1123  #
1124  # Modify these three files:
1125  #
1126  #    M      A/mu
1127  #    M      A/D/G/rho
1128  #    M      iota
1129  #
1130  # Then commit some of them using --depth=immediates:
1131  #
1132  #    svn ci -m "log msg" --depth=immediates wc_dir wc_dir/A/D/G/rho
1133  #
1134  # Before the bugfix, that would result in an error:
1135  #
1136  #    subversion/libsvn_wc/lock.c:570: (apr_err=155004)
1137  #    svn: Working copy '/blah/blah/blah/wc' locked
1138  #    svn: run 'svn cleanup' to remove locks \
1139  #         (type 'svn help cleanup' for details)
1140  #
1141  # After the bugfix, it correctly commits two of the three files:
1142  #
1143  #    Sending        A/D/G/rho
1144  #    Sending        iota
1145  #    Transmitting file data ..
1146  #    Committed revision 2.
1147
1148  iota_path = os.path.join(wc_dir, 'iota')
1149  mu_path   = os.path.join(wc_dir, 'A', 'mu')
1150  G_path    = os.path.join(wc_dir, 'A', 'D', 'G')
1151  rho_path  = os.path.join(G_path, 'rho')
1152
1153  svntest.main.file_append(iota_path, "new text in iota\n")
1154  svntest.main.file_append(mu_path,   "new text in mu\n")
1155  svntest.main.file_append(rho_path,  "new text in rho\n")
1156
1157  expected_output = svntest.wc.State(wc_dir, {
1158    'iota' : Item(verb='Sending'),
1159    'A/D/G/rho' : Item(verb='Sending'),
1160    })
1161  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1162  expected_status.tweak('iota',       status='  ',  wc_rev=2)
1163  expected_status.tweak('A/mu',       status='M ',  wc_rev=1)
1164  expected_status.tweak('A/D/G/rho',  status='  ',  wc_rev=2)
1165  svntest.actions.run_and_verify_commit(wc_dir,
1166                                        expected_output,
1167                                        expected_status,
1168                                        None,
1169                                        '--depth', 'immediates',
1170                                        wc_dir, G_path)
1171
1172def depth_immediates_receive_new_dir(sbox):
1173  "depth-immediates wc receives new directory"
1174
1175  ign_a, ign_b, wc_immed, wc = set_up_depthy_working_copies(sbox,
1176                                                            immediates=True,
1177                                                            infinity=True)
1178
1179  I_path = os.path.join(wc, 'I')
1180  zeta_path = os.path.join(wc, 'I', 'zeta')
1181  other_I_path = os.path.join(wc_immed, 'I')
1182
1183  os.mkdir(I_path)
1184  svntest.main.file_write(zeta_path, "This is the file 'zeta'.\n")
1185
1186  # Commit in the "other" wc.
1187  svntest.actions.run_and_verify_svn(None, None, [], 'add', I_path)
1188  expected_output = svntest.wc.State(wc, {
1189    'I'      : Item(verb='Adding'),
1190    'I/zeta' : Item(verb='Adding'),
1191    })
1192  expected_status = svntest.actions.get_virginal_state(wc, 1)
1193  expected_status.add({
1194    'I'      : Item(status='  ', wc_rev=2),
1195    'I/zeta' : Item(status='  ', wc_rev=2),
1196    })
1197  svntest.actions.run_and_verify_commit(wc,
1198                                        expected_output,
1199                                        expected_status,
1200                                        None, wc)
1201
1202  # Update the depth-immediates wc, expecting to receive just the
1203  # new directory, without the file.
1204  expected_output = svntest.wc.State(wc_immed, {
1205    'I'    : Item(status='A '),
1206    })
1207  expected_disk = svntest.wc.State('', {
1208    'iota' : Item(contents="This is the file 'iota'.\n"),
1209    'A'    : Item(),
1210    'I'    : Item(),
1211    })
1212  expected_status = svntest.wc.State(wc_immed, {
1213    ''     : Item(status='  ', wc_rev=2),
1214    'iota' : Item(status='  ', wc_rev=2),
1215    'A'    : Item(status='  ', wc_rev=2),
1216    'I'    : Item(status='  ', wc_rev=2),
1217    })
1218  svntest.actions.run_and_verify_update(wc_immed,
1219                                        expected_output,
1220                                        expected_disk,
1221                                        expected_status,
1222                                        None, None, None, None, None)
1223  # Check that the new directory was added at depth=empty.
1224  verify_depth(None, "empty", other_I_path)
1225
1226def add_tree_with_depth(sbox):
1227  "add multi-subdir tree with --depth options"  # For issue #2931
1228  sbox.build()
1229  wc_dir = sbox.wc_dir
1230  new1_path = os.path.join(wc_dir, 'new1')
1231  new2_path = os.path.join(new1_path, 'new2')
1232  new3_path = os.path.join(new2_path, 'new3')
1233  new4_path = os.path.join(new3_path, 'new4')
1234  os.mkdir(new1_path)
1235  os.mkdir(new2_path)
1236  os.mkdir(new3_path)
1237  os.mkdir(new4_path)
1238  # Simple case, add new1 only, set depth to files
1239  svntest.actions.run_and_verify_svn(None, None, [],
1240                                     "add", "--depth", "files", new1_path)
1241  verify_depth(None, "infinity", new1_path)
1242
1243  # Force add new1 at new1 again, should include new2 at empty, the depth of
1244  # new1 should not change
1245  svntest.actions.run_and_verify_svn(None, None, [],
1246                                     "add", "--depth", "immediates",
1247                                     "--force", new1_path)
1248  verify_depth(None, "infinity", new1_path)
1249  verify_depth(None, "infinity", new2_path)
1250
1251  # add new4 with intermediate path, the intermediate path is added at empty
1252  svntest.actions.run_and_verify_svn(None, None, [],
1253                                     "add", "--depth", "immediates",
1254                                     "--parents", new4_path)
1255  verify_depth(None, "infinity", new3_path)
1256  verify_depth(None, "infinity", new4_path)
1257
1258def upgrade_from_above(sbox):
1259  "upgrade a depth=empty wc from above"
1260
1261  # The bug was that 'svn up --set-depth=files' worked from within the
1262  # working copy, but not from without with working copy top given
1263  # as an argument.  Both ways would correctly cause 'iota' to
1264  # appear, but only the former actually upgraded the depth of the
1265  # working copy to 'files'.  See this thread for details:
1266  #
1267  #   http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=130157
1268  #   From: Alexander Sinyushkin <Alexander.Sinyushkin@svnkit.com>
1269  #   To: dev@subversion.tigris.org
1270  #   Subject: Problem upgrading working copy depth
1271  #   Date: Wed, 19 Sep 2007 23:15:24 +0700
1272  #   Message-ID: <46F14B1C.8010406@svnkit.com>
1273
1274  sbox2 = sbox.clone_dependent()
1275
1276  wc, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
1277
1278  # First verify that upgrading from within works.
1279  saved_cwd = os.getcwd()
1280  try:
1281    os.chdir(wc)
1282    expected_output = svntest.wc.State('', {
1283        'iota'    : Item(status='A '),
1284        })
1285    expected_disk = svntest.wc.State('', {
1286        'iota' : Item(contents="This is the file 'iota'.\n"),
1287        })
1288    expected_status = svntest.wc.State('', {
1289        ''     : Item(status='  ', wc_rev=1),
1290        'iota' : Item(status='  ', wc_rev=1),
1291        })
1292    svntest.actions.run_and_verify_update('',
1293                                          expected_output,
1294                                          expected_disk,
1295                                          expected_status,
1296                                          None, None, None, None, None, None,
1297                                          '--set-depth=files')
1298    verify_depth(None, "files")
1299  finally:
1300    os.chdir(saved_cwd)
1301
1302  # Do it again, this time from above the working copy.
1303  wc, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox2, empty=True)
1304  expected_output = svntest.wc.State(wc, {
1305      'iota'    : Item(status='A '),
1306      })
1307  expected_disk = svntest.wc.State('', {
1308      'iota' : Item(contents="This is the file 'iota'.\n"),
1309      })
1310  expected_status = svntest.wc.State(wc, {
1311      ''     : Item(status='  ', wc_rev=1),
1312      'iota' : Item(status='  ', wc_rev=1),
1313      })
1314  svntest.actions.run_and_verify_update(wc,
1315                                        expected_output,
1316                                        expected_disk,
1317                                        expected_status,
1318                                        None, None, None, None, None, None,
1319                                        '--set-depth=files', wc)
1320  verify_depth(None, "files", wc)
1321
1322def status_in_depthy_wc(sbox):
1323  "status -u at various depths in non-infinity wc"
1324
1325  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
1326                                                            infinity=True)
1327
1328  iota_path = os.path.join(wc, 'iota')
1329  A_path = os.path.join(wc, 'A')
1330  mu_path = os.path.join(wc, 'A', 'mu')
1331  gamma_path = os.path.join(wc, 'A', 'D', 'gamma')
1332
1333  # Make some changes in the depth-infinity wc, and commit them
1334  svntest.actions.run_and_verify_svn(None, None, [],
1335                                     'propset', 'foo', 'foo-val', wc)
1336  svntest.main.file_write(iota_path, "new text\n")
1337  svntest.actions.run_and_verify_svn(None, None, [],
1338                                     'propset', 'bar', 'bar-val', A_path)
1339  svntest.main.file_write(mu_path, "new text\n")
1340  svntest.main.file_write(gamma_path, "new text\n")
1341  svntest.actions.run_and_verify_svn(None, None, [],
1342                                     'commit', '-m', '', wc)
1343
1344  status = [
1345    "Status against revision:      2\n",
1346    "        *        1   .\n",
1347    "        *        1   iota\n",
1348    "        *        1   A\n",
1349    "        *        1   " + os.path.join('A', 'mu') + "\n",
1350  ]
1351
1352  os.chdir(wc_empty)
1353
1354  expected_output = svntest.verify.UnorderedOutput(status[:2])
1355  # The output should contain only the change on '.'.
1356  svntest.actions.run_and_verify_svn(None, expected_output, [],
1357                                     'st', '-u')
1358
1359  # Upgrade to depth-files.
1360  svntest.actions.run_and_verify_svn(None, None, [], 'up',
1361                                     '--set-depth', 'files', '-r1')
1362  # The output should contain only the changes on '.' and 'iota'.
1363  expected_output = svntest.verify.UnorderedOutput(status[:3])
1364  svntest.actions.run_and_verify_svn(None, expected_output, [],
1365                                     'st', '-u')
1366  # Do a status -u at --depth empty.
1367  expected_output = svntest.verify.UnorderedOutput(status[:2])
1368  svntest.actions.run_and_verify_svn(None, expected_output, [],
1369                                     'st', '-u', '--depth', 'empty')
1370
1371  # Upgrade to depth-immediates.
1372  svntest.actions.run_and_verify_svn(None, None, [], 'up',
1373                                     '--set-depth', 'immediates', '-r1')
1374  # The output should contain the changes on '.', 'A' and 'iota'.
1375  expected_output = svntest.verify.UnorderedOutput(status[:4])
1376  svntest.actions.run_and_verify_svn(None, expected_output, [],
1377                                    'st', '-u')
1378  # Do a status -u at --depth files.
1379  expected_output = svntest.verify.UnorderedOutput(status[:3])
1380  svntest.actions.run_and_verify_svn(None, expected_output, [],
1381                                     'st', '-u', '--depth', 'files')
1382
1383  # Upgrade A to depth-files.
1384  svntest.actions.run_and_verify_svn(None, None, [], 'up',
1385                                     '--set-depth', 'files', '-r1', 'A')
1386  # The output should contain everything but the change on
1387  # gamma (which does not exist in this working copy).
1388  expected_output = svntest.verify.UnorderedOutput(status)
1389  svntest.actions.run_and_verify_svn(None, expected_output, [],
1390                                     'st', '-u')
1391  # Do a status -u at --depth immediates.
1392  expected_output = svntest.verify.UnorderedOutput(status[:4])
1393  svntest.actions.run_and_verify_svn(None, expected_output, [],
1394                                    'st', '-u', '--depth', 'immediates')
1395
1396#----------------------------------------------------------------------
1397
1398# Issue #3039.
1399def depthy_update_above_dir_to_be_deleted(sbox):
1400  "'update -N' above a WC path deleted in repos HEAD"
1401  sbox.build()
1402
1403  sbox_for_depth = {
1404    "files" : sbox,
1405    "immediates" : sbox.clone_dependent(copy_wc=True),
1406    "empty" : sbox.clone_dependent(copy_wc=True),
1407    }
1408
1409  exit_code, output, err = svntest.actions.run_and_verify_svn(
1410    None, None, [],
1411    "delete", "-m", "Delete A.", sbox.repo_url + "/A")
1412
1413  def empty_output(wc_dir):
1414    return svntest.wc.State(wc_dir, { })
1415
1416  def output_with_A(wc_dir):
1417    expected_output = empty_output(wc_dir)
1418    expected_output.add({
1419      "A" : Item(status="D "),
1420      })
1421    return expected_output
1422
1423  initial_disk = svntest.main.greek_state.copy()
1424  disk_with_only_iota = svntest.wc.State("", {
1425    "iota" : Item("This is the file 'iota'.\n"),
1426    })
1427
1428  def status_with_dot(wc_dir):
1429    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1430    expected_status.tweak("", wc_rev=2)
1431    return expected_status
1432
1433  def status_with_iota(wc_dir):
1434    expected_status = status_with_dot(wc_dir)
1435    expected_status.tweak("iota", wc_rev=2)
1436    return expected_status
1437
1438  def status_with_only_iota(wc_dir):
1439    return svntest.wc.State(wc_dir, {
1440      ""     : Item(status="  ", wc_rev=2),
1441      "iota" : Item(status="  ", wc_rev=2),
1442      })
1443
1444  expected_trees_for_depth = {
1445    "files"      : (empty_output, initial_disk, status_with_iota),
1446    "immediates" : (output_with_A, disk_with_only_iota, status_with_only_iota),
1447    "empty"      : (empty_output, initial_disk, status_with_dot),
1448    }
1449
1450  for depth in sbox_for_depth.keys():
1451    wc_dir = sbox_for_depth[depth].wc_dir
1452    (expected_output_func, expected_disk, expected_status_func) = \
1453      expected_trees_for_depth[depth]
1454    #print depth
1455    svntest.actions.run_and_verify_update(wc_dir,
1456                                          expected_output_func(wc_dir),
1457                                          expected_disk,
1458                                          expected_status_func(wc_dir),
1459                                          None, None, None, None, None,
1460                                          False,
1461                                          "--depth=%s" % depth, wc_dir)
1462
1463
1464#----------------------------------------------------------------------
1465
1466# Tests for deselection interface (a.k.a folding subtrees).
1467#----------------------------------------------------------------------
1468def depth_folding_clean_trees_1(sbox):
1469  "gradually fold wc from depth=infinity to empty"
1470
1471  # Covers the following situations:
1472  #
1473  #  infinity->immediates (metadata only)
1474  #  immediates->files (metadata only)
1475  #  mixed(infinity+files)=>immediates
1476  #  infinity=>empty
1477  #  immediates=>empty
1478  #  mixed(infinity+empty)=>immediates
1479  #  mixed(infinity+empty/immediates)=>immediates
1480  #  immediates=>files
1481  #  files=>empty
1482  #  mixed(infinity+empty)=>files
1483
1484  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
1485                                                             infinity=True)
1486
1487  A_path = os.path.join(wc_dir, 'A')
1488  C_path = os.path.join(A_path, 'C')
1489  B_path = os.path.join(A_path, 'B')
1490  D_path = os.path.join(A_path, 'D')
1491  E_path = os.path.join(B_path, 'E')
1492  F_path = os.path.join(B_path, 'F')
1493  G_path = os.path.join(D_path, 'G')
1494  H_path = os.path.join(D_path, 'H')
1495
1496  # Run 'svn up --set-depth=immediates' to directory A/B/E.
1497  # This is an infinity=>immediates folding, changes on metadata only
1498  expected_output = svntest.wc.State(wc_dir, {})
1499  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1500  expected_disk = svntest.main.greek_state.copy()
1501  svntest.actions.run_and_verify_update(wc_dir,
1502                                        expected_output,
1503                                        expected_disk,
1504                                        expected_status,
1505                                        None, None,
1506                                        None, None, None, None,
1507                                        '--set-depth', 'immediates', E_path)
1508  verify_depth(None, "immediates", E_path)
1509
1510  # Run 'svn up --set-depth=files' to directory A/B/E.
1511  # This is an immediates=>files folding, changes on metadata only
1512  svntest.actions.run_and_verify_update(wc_dir,
1513                                        expected_output,
1514                                        expected_disk,
1515                                        expected_status,
1516                                        None, None,
1517                                        None, None, None, None,
1518                                        '--set-depth', 'files', E_path)
1519  verify_depth(None, "files", E_path)
1520
1521  # Run 'svn up --set-depth=immediates' to directory A/B.
1522  # This is an mixed(infinity+files)=>immediates folding
1523  expected_output = svntest.wc.State(wc_dir, {
1524    'A/B/E/alpha'    : Item(status='D '),
1525    'A/B/E/beta'     : Item(status='D '),
1526    })
1527  expected_status.remove('A/B/E/alpha', 'A/B/E/beta')
1528  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta')
1529  svntest.actions.run_and_verify_update(wc_dir,
1530                                        expected_output,
1531                                        expected_disk,
1532                                        expected_status,
1533                                        None, None,
1534                                        None, None, None, None,
1535                                        '--set-depth', 'immediates', B_path)
1536  verify_depth(None, "immediates", B_path)
1537  verify_depth(None, "empty", E_path)
1538  verify_depth(None, "empty", F_path)
1539
1540  # Run 'svn up --set-depth=empty' to directory A/D/H
1541  # This is an infinity=>empty folding.
1542  expected_output = svntest.wc.State(wc_dir, {
1543    'A/D/H/chi'      : Item(status='D '),
1544    'A/D/H/psi'      : Item(status='D '),
1545    'A/D/H/omega'    : Item(status='D ')
1546    })
1547  expected_status.remove( 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
1548  expected_disk.remove( 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
1549  svntest.actions.run_and_verify_update(wc_dir,
1550                                        expected_output,
1551                                        expected_disk,
1552                                        expected_status,
1553                                        None, None,
1554                                        None, None, None, None,
1555                                        '--set-depth', 'empty', H_path)
1556  verify_depth(None, "empty", H_path)
1557
1558  # Run 'svn up --set-depth=immediates' to directory A/D
1559  # This is an mixed(infinity+empty)=>immediates folding.
1560  expected_output = svntest.wc.State(wc_dir, {
1561    'A/D/G/pi'       : Item(status='D '),
1562    'A/D/G/rho'      : Item(status='D '),
1563    'A/D/G/tau'      : Item(status='D '),
1564    })
1565  expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1566  expected_disk.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1567  svntest.actions.run_and_verify_update(wc_dir,
1568                                        expected_output,
1569                                        expected_disk,
1570                                        expected_status,
1571                                        None, None,
1572                                        None, None, None, None,
1573                                        '--set-depth', 'immediates', D_path)
1574  verify_depth(None, "immediates", D_path)
1575  verify_depth(None, "empty", G_path)
1576
1577  # Run 'svn up --set-depth=empty' to directory A/D
1578  # This is an immediates=>empty folding.
1579  expected_output = svntest.wc.State(wc_dir, {
1580    'A/D/G'          : Item(status='D '),
1581    'A/D/H'          : Item(status='D '),
1582    'A/D/gamma'      : Item(status='D ')
1583    })
1584  expected_status.remove('A/D/gamma', 'A/D/G', 'A/D/H')
1585  expected_disk.remove('A/D/gamma', 'A/D/G', 'A/D/H')
1586  svntest.actions.run_and_verify_update(wc_dir,
1587                                        expected_output,
1588                                        expected_disk,
1589                                        expected_status,
1590                                        None, None,
1591                                        None, None, None, None,
1592                                        '--set-depth', 'empty', D_path)
1593  verify_depth(None, "empty", D_path)
1594
1595  # Run 'svn up --set-depth=immediates' to directory A
1596  # This is an mixed(infinity+empty/immediates)=>immediates folding.
1597  expected_output = svntest.wc.State(wc_dir, {
1598    'A/B/E'          : Item(status='D '),
1599    'A/B/F'          : Item(status='D '),
1600    'A/B/lambda'     : Item(status='D ')
1601    })
1602  expected_status.remove('A/B/lambda', 'A/B/E', 'A/B/F')
1603  expected_disk.remove('A/B/lambda', 'A/B/E', 'A/B/F')
1604  svntest.actions.run_and_verify_update(wc_dir,
1605                                        expected_output,
1606                                        expected_disk,
1607                                        expected_status,
1608                                        None, None,
1609                                        None, None, None, None,
1610                                        '--set-depth', 'immediates', A_path)
1611  verify_depth(None, "immediates", A_path)
1612  verify_depth(None, "empty", C_path)
1613  verify_depth(None, "empty", B_path)
1614
1615  # Run 'svn up --set-depth=files' to directory A
1616  # This is an immediates=>files folding.
1617  expected_output = svntest.wc.State(wc_dir, {
1618    'A/B'            : Item(status='D '),
1619    'A/C'            : Item(status='D '),
1620    'A/D'            : Item(status='D ')
1621    })
1622  expected_status.remove('A/B', 'A/C', 'A/D')
1623  expected_disk.remove('A/B', 'A/C', 'A/D')
1624  svntest.actions.run_and_verify_update(wc_dir,
1625                                        expected_output,
1626                                        expected_disk,
1627                                        expected_status,
1628                                        None, None,
1629                                        None, None, None, None,
1630                                        '--set-depth', 'files', A_path)
1631  verify_depth(None, "files", A_path)
1632
1633  # Run 'svn up --set-depth=empty' to directory A
1634  # This is an files=>empty folding.
1635  expected_output = svntest.wc.State(wc_dir, {
1636    'A/mu'            : Item(status='D ')
1637    })
1638  expected_status.remove('A/mu')
1639  expected_disk.remove('A/mu')
1640  svntest.actions.run_and_verify_update(wc_dir,
1641                                        expected_output,
1642                                        expected_disk,
1643                                        expected_status,
1644                                        None, None,
1645                                        None, None, None, None,
1646                                        '--set-depth', 'empty', A_path)
1647  verify_depth(None, "empty", A_path)
1648
1649  # Run 'svn up --set-depth=files' to wc
1650  # This is an mixed(infinity+empty)=>files folding.
1651  expected_output = svntest.wc.State(wc_dir, {
1652    'A'            : Item(status='D ')
1653    })
1654  expected_status.remove('A')
1655  expected_disk.remove('A')
1656  svntest.actions.run_and_verify_update(wc_dir,
1657                                        expected_output,
1658                                        expected_disk,
1659                                        expected_status,
1660                                        None, None,
1661                                        None, None, None, None,
1662                                        '--set-depth', 'files', wc_dir)
1663  verify_depth(None, "files", wc_dir)
1664
1665
1666#------------------------------------------------------------------------------
1667def depth_folding_clean_trees_2(sbox):
1668  "gradually fold wc, focusing on depth=immediates"
1669
1670  # Covers the following situations:
1671  #
1672  #  infinity=>immediates
1673  #  mixed(immediates+immediates)=>immediates
1674  #  mixed(immediates+infinity)=>immediates
1675  #  mixed(immediates+files)=>immediates
1676  #  immediates=>empty(remove the target since the parent is at files/empty)
1677
1678  ign_a, wc_dir, ign_b, ign_c = set_up_depthy_working_copies(sbox, files=True)
1679
1680  A_path = os.path.join(wc_dir, 'A')
1681  D_path = os.path.join(A_path, 'D')
1682  H_path = os.path.join(D_path, 'H')
1683  G_path = os.path.join(D_path, 'G')
1684
1685  # pull in directory A at immediates
1686  svntest.actions.run_and_verify_svn(None, None, [],
1687                                     'up', '--depth', 'immediates', A_path)
1688  # check to see if it's really at immediates
1689  verify_depth(None, "immediates", A_path)
1690
1691  # pull in directory D at infinity
1692  svntest.actions.run_and_verify_svn(None, None, [],
1693                                     'up', '--set-depth', 'infinity', D_path)
1694
1695  # Run 'svn up --set-depth=immediates' to directory A/D.
1696  # This is an infinity=>immediates folding
1697  expected_output = svntest.wc.State(wc_dir, {
1698    'A/D/G/pi'       : Item(status='D '),
1699    'A/D/G/rho'      : Item(status='D '),
1700    'A/D/G/tau'      : Item(status='D '),
1701    'A/D/H/chi'      : Item(status='D '),
1702    'A/D/H/psi'      : Item(status='D '),
1703    'A/D/H/omega'    : Item(status='D ')
1704    })
1705  expected_status = svntest.wc.State(wc_dir, {
1706    ''               : Item(status='  ', wc_rev=1),
1707    'iota'           : Item(status='  ', wc_rev=1),
1708    'A'              : Item(status='  ', wc_rev=1),
1709    'A/mu'           : Item(status='  ', wc_rev=1),
1710    'A/B'            : Item(status='  ', wc_rev=1),
1711    'A/C'            : Item(status='  ', wc_rev=1),
1712    'A/D'            : Item(status='  ', wc_rev=1),
1713    'A/D/gamma'      : Item(status='  ', wc_rev=1),
1714    'A/D/G'          : Item(status='  ', wc_rev=1),
1715    'A/D/H'          : Item(status='  ', wc_rev=1)
1716    })
1717  expected_disk = svntest.wc.State('', {
1718    'iota'        : Item(contents="This is the file 'iota'.\n"),
1719    'A'           : Item(contents=None),
1720    'A/mu'        : Item(contents="This is the file 'mu'.\n"),
1721    'A/B'         : Item(contents=None),
1722    'A/C'         : Item(contents=None),
1723    'A/D'         : Item(contents=None),
1724    'A/D/gamma'   : Item(contents="This is the file 'gamma'.\n"),
1725    'A/D/G'       : Item(contents=None),
1726    'A/D/H'       : Item(contents=None),
1727    })
1728  svntest.actions.run_and_verify_update(wc_dir,
1729                                        expected_output,
1730                                        expected_disk,
1731                                        expected_status,
1732                                        None, None,
1733                                        None, None, None, None,
1734                                        '--set-depth', 'immediates', D_path)
1735  verify_depth(None, "immediates", D_path)
1736  verify_depth(None, "empty", G_path)
1737  verify_depth(None, "empty", H_path)
1738
1739  # Run 'svn up --set-depth=immediates' to directory A.
1740  # This is an mixed(immediates+immediates)=>immediates folding
1741  expected_output = svntest.wc.State(wc_dir, {
1742    'A/D/G'      : Item(status='D '),
1743    'A/D/H'      : Item(status='D '),
1744    'A/D/gamma'  : Item(status='D ')
1745    })
1746  expected_status.remove( 'A/D/G', 'A/D/H', 'A/D/gamma')
1747  expected_disk.remove( 'A/D/G', 'A/D/H', 'A/D/gamma')
1748  svntest.actions.run_and_verify_update(wc_dir,
1749                                        expected_output,
1750                                        expected_disk,
1751                                        expected_status,
1752                                        None, None,
1753                                        None, None, None, None,
1754                                        '--set-depth', 'immediates', A_path)
1755  verify_depth(None, "immediates", A_path)
1756  verify_depth(None, "empty", D_path)
1757
1758  # pull in directory D at infinity
1759  svntest.actions.run_and_verify_svn(None, None, [],
1760                                     'up', '--set-depth', 'infinity', D_path)
1761
1762  # Run 'svn up --set-depth=immediates' to directory A.
1763  # This is an mixed(immediates+infinity)=>immediates folding
1764  expected_output = svntest.wc.State(wc_dir, {
1765    'A/D/gamma'      : Item(status='D '),
1766    'A/D/G'          : Item(status='D '),
1767    'A/D/H'          : Item(status='D '),
1768    })
1769  svntest.actions.run_and_verify_update(wc_dir,
1770                                        expected_output,
1771                                        expected_disk,
1772                                        expected_status,
1773                                        None, None,
1774                                        None, None, None, None,
1775                                        '--set-depth', 'immediates', A_path)
1776  verify_depth(None, "immediates", A_path)
1777  verify_depth(None, "empty", D_path)
1778
1779  # pull in directory D at files
1780  svntest.actions.run_and_verify_svn(None, None, [],
1781                                     'up', '--set-depth', 'files', D_path)
1782
1783  # Run 'svn up --set-depth=immediates' to directory A.
1784  # This is an mixed(immediates+files)=>immediates folding
1785  expected_output = svntest.wc.State(wc_dir, {
1786    'A/D/gamma'      : Item(status='D ')
1787    })
1788  svntest.actions.run_and_verify_update(wc_dir,
1789                                        expected_output,
1790                                        expected_disk,
1791                                        expected_status,
1792                                        None, None,
1793                                        None, None, None, None,
1794                                        '--set-depth', 'immediates', A_path)
1795  verify_depth(None, "immediates", A_path)
1796  verify_depth(None, "empty", D_path)
1797
1798#  Comment the following out, since cropping out the root of tree is now
1799#  handled by svn_depth_exclude and should have a separate test case for all
1800#  influenced commands.
1801#
1802#  # Run 'svn up --set-depth=empty' to directory A.
1803#  # This is an immediates=>empty folding, the directory A should be deleted
1804#  # too since the parent directory is at files/empty
1805#  expected_output = svntest.wc.State(wc_dir, {
1806#    'A'              : Item(status='D '),
1807#    })
1808#  expected_status = svntest.wc.State(wc_dir, {
1809#    ''               : Item(status='  ', wc_rev=1),
1810#    'iota'           : Item(status='  ', wc_rev=1)
1811#    })
1812#  expected_disk = svntest.wc.State('', {
1813#    'iota'        : Item(contents="This is the file 'iota'.\n")
1814#    })
1815#  svntest.actions.run_and_verify_update(wc_dir,
1816#                                        expected_output,
1817#                                        expected_disk,
1818#                                        expected_status,
1819#                                        None, None,
1820#                                        None, None, None, None,
1821#                                        '--set-depth', 'empty', A_path)
1822
1823def depth_fold_expand_clean_trees(sbox):
1824  "expand target while contracting subtree"
1825  #  --set-depth=immediates/files to an empty target with infinity
1826  #  sub-tree should both fold the subtree and expand the target
1827
1828  wc_dir, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
1829
1830  A_path = os.path.join(wc_dir, 'A')
1831  B_path = os.path.join(A_path, 'B')
1832  C_path = os.path.join(A_path, 'C')
1833  D_path = os.path.join(A_path, 'D')
1834
1835  # pull in directory A at empty
1836  svntest.actions.run_and_verify_svn(None, None, [],
1837                                     'up', '--depth', 'empty', A_path)
1838  verify_depth(None, "empty", A_path)
1839
1840  # pull in directory D at infinity
1841  svntest.actions.run_and_verify_svn(None, None, [],
1842                                     'up', D_path)
1843
1844  # Make the other working copy.
1845  other_wc = sbox.add_wc_path('other')
1846  svntest.actions.duplicate_dir(wc_dir, other_wc)
1847
1848  # Run 'svn up --set-depth=immediates' to directory A. This both folds
1849  # directory D to empty and expands directory A to immediates
1850  expected_output = svntest.wc.State(wc_dir, {
1851    'A/mu'           : Item(status='A '),
1852    'A/B'            : Item(status='A '),
1853    'A/C'            : Item(status='A '),
1854    'A/D/gamma'      : Item(status='D '),
1855    'A/D/G'          : Item(status='D '),
1856    'A/D/H'          : Item(status='D '),
1857    })
1858  expected_status = svntest.wc.State(wc_dir, {
1859    ''               : Item(status='  ', wc_rev=1),
1860    'A'              : Item(status='  ', wc_rev=1),
1861    'A/mu'           : Item(status='  ', wc_rev=1),
1862    'A/B'            : Item(status='  ', wc_rev=1),
1863    'A/C'            : Item(status='  ', wc_rev=1),
1864    'A/D'            : Item(status='  ', wc_rev=1)
1865    })
1866  expected_disk = svntest.wc.State('', {
1867    'A'           : Item(contents=None),
1868    'A/mu'        : Item(contents="This is the file 'mu'.\n"),
1869    'A/B'         : Item(contents=None),
1870    'A/C'         : Item(contents=None),
1871    'A/D'         : Item(contents=None)
1872    })
1873  svntest.actions.run_and_verify_update(wc_dir,
1874                                        expected_output,
1875                                        expected_disk,
1876                                        expected_status,
1877                                        None, None,
1878                                        None, None, None, None,
1879                                        '--set-depth', 'immediates', A_path)
1880  verify_depth(None, "immediates", A_path)
1881  verify_depth(None, "empty", B_path)
1882  verify_depth(None, "empty", C_path)
1883  verify_depth(None, "empty", D_path)
1884
1885  # Run 'svn up --set-depth=files' to directory A in other_wc. This both
1886  # removes directory D and expands directory A to files
1887  expected_output = svntest.wc.State(other_wc, {
1888    'A/mu'           : Item(status='A '),
1889    'A/D'            : Item(status='D '),
1890    })
1891  expected_status = svntest.wc.State(other_wc, {
1892    ''               : Item(status='  ', wc_rev=1),
1893    'A'              : Item(status='  ', wc_rev=1),
1894    'A/mu'           : Item(status='  ', wc_rev=1),
1895    })
1896  expected_disk = svntest.wc.State('', {
1897    'A'           : Item(contents=None),
1898    'A/mu'        : Item(contents="This is the file 'mu'.\n")
1899    })
1900  Other_A_path = os.path.join(other_wc, 'A')
1901  svntest.actions.run_and_verify_update(other_wc,
1902                                        expected_output,
1903                                        expected_disk,
1904                                        expected_status,
1905                                        None, None,
1906                                        None, None, None, None,
1907                                        '--set-depth', 'files', Other_A_path)
1908  verify_depth(None, "files", Other_A_path)
1909
1910
1911def pull_in_tree_with_depth_option(sbox):
1912  """checkout and verify subtree with depth immediates"""
1913
1914  wc_empty,ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox,
1915                                                              empty=True)
1916  A_path = os.path.join(wc_empty, 'A')
1917  expected_output = svntest.wc.State(wc_empty, {
1918    'A'      : Item(status='A '),
1919    'A/mu'   : Item(status='A '),
1920    'A/B'    : Item(status='A '),
1921    'A/C'    : Item(status='A '),
1922    'A/D'    : Item(status='A ')
1923    })
1924  expected_disk = svntest.wc.State('', {
1925    'A'      : Item(),
1926    'A/mu'   : Item("This is the file 'mu'.\n"),
1927    'A/B'    : Item(),
1928    'A/C'    : Item(),
1929    'A/D'    : Item(),
1930    })
1931  expected_status = svntest.wc.State(wc_empty, {
1932    ''       : Item(status='  ', wc_rev=1),
1933    'A'      : Item(status='  ', wc_rev=1),
1934    'A/mu'   : Item(status='  ', wc_rev=1),
1935    'A/B'    : Item(status='  ', wc_rev=1),
1936    'A/C'    : Item(status='  ', wc_rev=1),
1937    'A/D'    : Item(status='  ', wc_rev=1),
1938    })
1939  svntest.actions.run_and_verify_update(wc_empty,
1940                                        expected_output,
1941                                        expected_disk,
1942                                        expected_status,
1943                                        None, None, None, None, None, False,
1944                                        "--depth=immediates", A_path)
1945
1946  # Check that the A directory was pull ed in at depth=immediates.
1947  verify_depth(None, "immediates", A_path)
1948
1949def fold_tree_with_unversioned_modified_items(sbox):
1950  "unversioned & modified items left untouched"
1951  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
1952                                                             infinity=True)
1953
1954  A_path = os.path.join(wc_dir, 'A')
1955  pi_path = os.path.join(A_path, 'D', 'G', 'pi')
1956  mu_path = os.path.join(A_path, 'mu')
1957  unv_path = os.path.join(A_path, 'B', 'unv')
1958
1959  # Modify file pi
1960  svntest.main.file_write(pi_path, "pi modified\n")
1961  # Modify file mu
1962  svntest.main.file_write(mu_path, "mu modified\n")
1963  # Create an unversioned file
1964  svntest.main.file_write(unv_path, "new unversioned\n")
1965
1966  # Fold the A dir to empty, expect the modified & unversioned ones left
1967  # unversioned rather than removed, along with paths to those items.
1968
1969  # Even though the directory B and D is not deleted because of local
1970  # modificatoin or unversioned items, there will be only one notification at
1971  # B and D.
1972  expected_output = svntest.wc.State(wc_dir, {
1973    'A/B'            : Item(status='D '),
1974    'A/C'            : Item(status='D '),
1975    'A/D'            : Item(status='D '),
1976    'A/mu'           : Item(status='D '),
1977    })
1978  # unversioned items will be ignored in in the status tree, since the
1979  # run_and_verify_update() function uses a quiet version of svn status
1980  # Dir A is still versioned, since the wc root is in depth-infinity
1981  expected_status = svntest.wc.State(wc_dir, {
1982    ''               : Item(status='  ', wc_rev=1),
1983    'iota'           : Item(status='  ', wc_rev=1),
1984    'A'              : Item(status='  ', wc_rev=1)
1985    })
1986  expected_disk = svntest.wc.State('', {
1987    'iota'           : Item(contents="This is the file 'iota'.\n"),
1988    'A'              : Item(contents=None),
1989    'A/mu'           : Item(contents="mu modified\n"),
1990    'A/B'            : Item(contents=None),
1991    'A/B/unv'        : Item(contents="new unversioned\n"),
1992    'A/D'            : Item(contents=None),
1993    'A/D/G'          : Item(contents=None),
1994    'A/D/G/pi'       : Item(contents="pi modified\n")
1995    })
1996  svntest.actions.run_and_verify_update(wc_dir,
1997                                        expected_output,
1998                                        expected_disk,
1999                                        expected_status,
2000                                        None, None,
2001                                        None, None, None, None,
2002                                        '--set-depth', 'empty', A_path)
2003  verify_depth(None, "empty", A_path)
2004
2005def depth_empty_update_on_file(sbox):
2006  "depth-empty update on a file doesn't break it"
2007  sbox.build()
2008  wc_dir = sbox.wc_dir
2009
2010  iota_path = os.path.join(wc_dir, 'iota')
2011
2012  # Change iota and commit it in r2.
2013  svntest.main.file_write(iota_path, 'Modified iota\n')
2014  expected_output = svntest.wc.State(wc_dir, { 'iota' : Item(verb='Sending'), })
2015  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2016  expected_status.tweak('iota', wc_rev=2, status='  ')
2017  svntest.actions.run_and_verify_commit(wc_dir,
2018                                        expected_output,
2019                                        expected_status,
2020                                        None, wc_dir)
2021
2022  # Update iota with depth=empty.
2023  expected_output = svntest.wc.State(wc_dir,
2024                                     {'iota': Item(status='U ') })
2025  expected_disk = svntest.main.greek_state.copy()
2026  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2027  svntest.actions.run_and_verify_update(wc_dir,
2028                                        expected_output,
2029                                        expected_disk,
2030                                        expected_status,
2031                                        None, None, None, None, None, False,
2032                                        '--depth=empty', '-r1', iota_path)
2033
2034  # Check the revision and created rev.
2035  svntest.actions.run_and_verify_svn_match_any('rev is right',
2036                                               r'^Revision: 1\n$',
2037                                               [], 'info', iota_path)
2038  svntest.actions.run_and_verify_svn_match_any('created rev is right',
2039                                               r'^Last Changed Rev: 1\n$',
2040                                               [], 'info', iota_path)
2041
2042
2043def excluded_path_update_operation(sbox):
2044  """make sure update handle svn_depth_exclude properly"""
2045
2046  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
2047                                                             infinity=True)
2048  A_path = os.path.join(wc_dir, 'A')
2049  B_path = os.path.join(A_path, 'B')
2050  L_path = os.path.join(A_path, 'L')
2051  E_path = os.path.join(B_path, 'E')
2052
2053  # Simply exclude a subtree
2054  expected_output = svntest.wc.State(wc_dir, {
2055    'A/B/E'            : Item(status='D '),
2056    })
2057  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2058  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
2059  expected_disk = svntest.main.greek_state.copy()
2060  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
2061
2062  svntest.actions.run_and_verify_update(wc_dir,
2063                                        expected_output,
2064                                        expected_disk,
2065                                        expected_status,
2066                                        None, None,
2067                                        None, None, None, None,
2068                                        '--set-depth', 'exclude', E_path)
2069  # verify_depth exclude? not implemented yet
2070
2071  # crop path B to immediates, this just pull in A/B/E again
2072  expected_output = svntest.wc.State(wc_dir, {
2073    'A/B/E'            : Item(status='A '),
2074    })
2075  expected_status.add({
2076    'A/B/E'            : Item(status='  ', wc_rev=1)
2077    })
2078  expected_disk.add({
2079    'A/B/E'          : Item(contents=None),
2080    })
2081  svntest.actions.run_and_verify_update(wc_dir,
2082                                        expected_output,
2083                                        expected_disk,
2084                                        expected_status,
2085                                        None, None,
2086                                        None, None, None, None,
2087                                        '--set-depth', 'immediates', B_path)
2088  verify_depth(None, "immediates", B_path)
2089
2090  # Exclude A/B/E again
2091  svntest.actions.run_and_verify_svn(None, None, [],
2092                                     'up', '--set-depth', 'exclude', E_path)
2093
2094  # Exclude path B totally, in which contains an excluded subtree.
2095  expected_output = svntest.wc.State(wc_dir, {
2096    'A/B'            : Item(status='D '),
2097    })
2098  expected_status.remove('A/B/F', 'A/B/E', 'A/B/lambda', 'A/B');
2099  expected_disk.remove('A/B/F', 'A/B/E', 'A/B/lambda', 'A/B');
2100  svntest.actions.run_and_verify_update(wc_dir,
2101                                        expected_output,
2102                                        expected_disk,
2103                                        expected_status,
2104                                        None, None,
2105                                        None, None, None, None,
2106                                        '--set-depth', 'exclude', B_path)
2107
2108  # Explicitly pull in excluded path B.
2109  expected_output = svntest.wc.State(wc_dir, {
2110    'A/B'            : Item(status='A '),
2111    'A/B/lambda'     : Item(status='A '),
2112    'A/B/E'          : Item(status='A '),
2113    'A/B/E/alpha'    : Item(status='A '),
2114    'A/B/E/beta'     : Item(status='A '),
2115    'A/B/F'          : Item(status='A '),
2116    })
2117  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2118  expected_disk = svntest.main.greek_state.copy()
2119  svntest.actions.run_and_verify_update(wc_dir,
2120                                        expected_output,
2121                                        expected_disk,
2122                                        expected_status,
2123                                        None, None,
2124                                        None, None, None, None,
2125                                        B_path)
2126
2127def excluded_path_misc_operation(sbox):
2128  """make sure other subcommands handle exclude"""
2129
2130  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
2131                                                             infinity=True)
2132  A_path = os.path.join(wc_dir, 'A')
2133  B_path = os.path.join(A_path, 'B')
2134  L_path = os.path.join(A_path, 'L')
2135  E_path = os.path.join(B_path, 'E')
2136  LE_path = os.path.join(L_path, 'E')
2137
2138  # Simply exclude a subtree
2139  expected_output = svntest.wc.State(wc_dir, {
2140    'A/B/E'            : Item(status='D '),
2141    })
2142  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2143  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
2144  expected_disk = svntest.main.greek_state.copy()
2145  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E');
2146
2147  svntest.actions.run_and_verify_update(wc_dir,
2148                                        expected_output,
2149                                        expected_disk,
2150                                        expected_status,
2151                                        None, None,
2152                                        None, None, None, None,
2153                                        '--set-depth', 'exclude', E_path)
2154
2155  # copy A/B to A/L, excluded entry should be copied too
2156  expected_output = ['A         '+L_path+'\n']
2157  svntest.actions.run_and_verify_svn(None, expected_output, [],
2158                                     'cp', B_path, L_path)
2159  # verify_depth exclude? not implemented yet
2160  #verify_depth(None, "empty", LE_path)
2161
2162  # revert A/L, with an excluded item in the tree
2163  expected_output = ["Reverted '"+L_path+"'\n"]
2164  svntest.actions.run_and_verify_svn(None, expected_output, [],
2165                                     'revert', '--depth=infinity', L_path)
2166
2167  # Get rid of A/L.
2168  svntest.actions.run_and_verify_svn(None, None, [],
2169                                     'rm', '--force', L_path)
2170
2171  # copy A/B to A/L again, excluded entry should be copied too
2172  expected_output = ['A         '+L_path+'\n']
2173  svntest.actions.run_and_verify_svn(None, expected_output, [],
2174                                     'cp', B_path, L_path)
2175
2176  # commit this copy, with an excluded item.
2177  expected_output = svntest.wc.State(wc_dir, { 'A/L' : Item(verb='Adding'), })
2178  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2179  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
2180  expected_status.add({
2181    'A/L'        : Item(status='  ', wc_rev=2),
2182    'A/L/lambda' : Item(status='  ', wc_rev=2),
2183    'A/L/F'      : Item(status='  ', wc_rev=2),
2184    })
2185  svntest.actions.run_and_verify_commit(wc_dir,
2186                                        expected_output,
2187                                        expected_status,
2188                                        None,
2189                                        wc_dir)
2190
2191  # Relocate wc, with excluded items in it.
2192  repo_dir = sbox.repo_dir
2193  repo_url = sbox.repo_url
2194  other_repo_dir, other_repo_url = sbox.add_repo_path('other')
2195  svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 0)
2196  svntest.main.safe_rmtree(repo_dir, 1)
2197  svntest.actions.run_and_verify_svn(None, None, [], 'switch', '--relocate',
2198                                     repo_url, other_repo_url, wc_dir)
2199
2200  # remove the new directory A/L, with an excluded item.
2201  # If successed, no error will be thrown
2202  svntest.actions.run_and_verify_svn(None, None, [],
2203                                     'rm', L_path)
2204
2205  # revert the delete
2206  # If successed, no error will be thrown
2207  svntest.actions.run_and_verify_svn(None, None, [],
2208                                     'revert', '--depth=infinity', L_path)
2209
2210
2211def excluded_receive_remote_removal(sbox):
2212  """exclude flag should be cleared upon remote removal"""
2213  ign_a, ign_b, ign_c, wc \
2214         = set_up_depthy_working_copies(sbox, infinity=True)
2215
2216  A_path = os.path.join(wc, 'A')
2217  B_path = os.path.join(A_path, 'B')
2218  C_path = os.path.join(A_path, 'C')
2219
2220  # Exclude path B from wc
2221  expected_output = svntest.wc.State(wc, {
2222    'A/B'            : Item(status='D '),
2223    })
2224  expected_disk = svntest.main.greek_state.copy()
2225  expected_disk.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2226                       'A/B/E', 'A/B/F', 'A/B')
2227  expected_status = svntest.actions.get_virginal_state(wc, 1)
2228  expected_status.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2229                         'A/B/E', 'A/B/F', 'A/B')
2230  svntest.actions.run_and_verify_update(wc,
2231                                        expected_output,
2232                                        expected_disk,
2233                                        expected_status,
2234                                        None, None,
2235                                        None, None, None, None,
2236                                        "--set-depth", "exclude", B_path)
2237
2238  # Remove path B in the repos.
2239  svntest.actions.run_and_verify_svn(None, None, [], "delete", "-m",
2240                                     "Delete B.", sbox.repo_url + "/A/B")
2241
2242  # Update wc, should receive the removal of excluded path B
2243  # and handle it silently.
2244  expected_status = svntest.actions.get_virginal_state(wc, 2)
2245  expected_status.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2246                         'A/B/E', 'A/B/F', 'A/B')
2247  svntest.actions.run_and_verify_update(wc,
2248                                        None,
2249                                        expected_disk,
2250                                        expected_status,
2251                                        None, None,
2252                                        None, None, None, None)
2253
2254  # Introduce a new path with the same name B.
2255  # This should succeed if the exclude entry is gone with the update,
2256  # otherwise a name conflict will rise up.
2257  expected_output = ['A         '+B_path+'\n']
2258  svntest.actions.run_and_verify_svn(None, expected_output, [],
2259                                     'cp', C_path, B_path)
2260
2261
2262# Regression test for r36686.
2263def exclude_keeps_hidden_entries(sbox):
2264  "'up --set-depth exclude' doesn't lose entries"
2265
2266  sbox.build()
2267  wc_dir = sbox.wc_dir
2268
2269  A_path = os.path.join(wc_dir, 'A')
2270  os.chdir(A_path)
2271
2272  # the second 'up' used to cause the entry of 'C' to be lost.
2273  svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', 'C')
2274  svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', 'D')
2275  # we could grep the 'entries' file, but...
2276  expected_stderr = ".*svn: 'C' is already under version control.*"
2277  svntest.actions.run_and_verify_svn(None, None, expected_stderr,
2278                                     'mkdir', 'C')
2279
2280
2281#----------------------------------------------------------------------
2282# Check that "svn resolved" visits tree-conflicts *on unversioned items*
2283# according to the --depth parameter.
2284
2285def make_depth_tree_conflicts(sbox):
2286  "Helper for tree_conflicts_resolved_depth_*"
2287
2288  sbox.build()
2289  wc = sbox.wc_dir
2290
2291  j = os.path.join
2292  A = j(wc, 'A')
2293  m =    j(A, 'mu')
2294  B =    j(A, 'B')
2295  D =    j(A, 'D')
2296  g =      j(D, 'gamma')
2297
2298  # Store node modifications as rev 2
2299  svntest.actions.run_and_verify_svn(None, None, [],
2300                                     'propset', 'foo', 'foo-val', B)
2301  svntest.main.file_append(m, "Modified mu.\n")
2302  svntest.main.file_append(g, "Modified gamma.\n")
2303
2304  expected_output = svntest.wc.State(wc, {
2305      'A/mu'              : Item(verb='Sending'),
2306      'A/B'               : Item(verb='Sending'),
2307      'A/D/gamma'         : Item(verb='Sending'),
2308    })
2309
2310  expected_status = svntest.actions.get_virginal_state(wc, 1)
2311  expected_status.tweak('A/mu', 'A/B', 'A/D/gamma',
2312                        wc_rev = 2)
2313
2314  svntest.actions.run_and_verify_commit(wc,
2315                                        expected_output,
2316                                        expected_status,
2317                                        None,
2318                                        A)
2319
2320  # Go back to rev 1
2321  expected_output = svntest.wc.State(wc, {
2322    'A/mu'              : Item(status='U '),
2323    'A/B'               : Item(status=' U'),
2324    'A/D/gamma'         : Item(status='U '),
2325  })
2326  expected_status = svntest.actions.get_virginal_state(wc, 1)
2327  expected_disk = svntest.main.greek_state.copy()
2328  svntest.actions.run_and_verify_update(wc,
2329                                        expected_output,
2330                                        expected_disk,
2331                                        expected_status,
2332                                        None, None, None, None, None, False,
2333                                        '-r1', A)
2334
2335  # Perform node deletions so that items become unversioned and
2336  # will have tree-conflicts upon update.
2337  svntest.actions.run_and_verify_svn(None, None, [],
2338                                     'rm', m, B, g)
2339
2340  # Update so that conflicts appear
2341  expected_output = svntest.wc.State(wc, {
2342    'A/mu'              : Item(status='  ', treeconflict='C'),
2343    'A/B'               : Item(status='  ', treeconflict='C'),
2344    'A/D/gamma'         : Item(status='  ', treeconflict='C'),
2345  })
2346
2347  expected_disk = svntest.main.greek_state.copy()
2348  expected_disk.remove('A/mu',
2349                       'A/B', 'A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2350                       'A/D/gamma');
2351
2352  # This test is set XFail because this (correct) status cannot be
2353  # verified due to an "svn update" bug. The tree-conflict on A/B
2354  # which is notified about during the update does not show in the
2355  # status. When removing file 'mu' from above 'rm' command, 'B' is
2356  # reported as tree-conflicted correctly. Also use these to verify:
2357  #  expected_output = None
2358  #  expected_disk = None
2359  expected_status = svntest.actions.get_virginal_state(wc, 2)
2360  expected_status.tweak('A/mu',
2361                        'A/B', 'A/B/lambda',
2362                        'A/B/E', 'A/B/E/alpha', 'A/B/E/beta',
2363                        'A/B/F',
2364                        'A/D/gamma',
2365                        status='D ')
2366  expected_status.tweak('A/mu', 'A/B', 'A/D/gamma',
2367                        treeconflict='C')
2368
2369  svntest.actions.run_and_verify_update(wc,
2370                                        expected_output,
2371                                        expected_disk,
2372                                        expected_status,
2373                                        None, None, None, None, None, False,
2374                                        wc)
2375
2376
2377
2378def tree_conflicts_resolved_depth_empty(sbox):
2379  "tree conflicts resolved depth-empty"
2380
2381  make_depth_tree_conflicts(sbox)
2382
2383  wc = sbox.wc_dir
2384  A = os.path.join(wc, 'A')
2385
2386  svntest.actions.run_and_verify_resolved([], '--depth=empty', A)
2387
2388
2389def tree_conflicts_resolved_depth_files(sbox):
2390  "tree conflicts resolved depth-files"
2391
2392  make_depth_tree_conflicts(sbox)
2393
2394  wc = sbox.wc_dir
2395  j = os.path.join
2396  A = j(wc, 'A')
2397  m =    j(A, 'mu')
2398
2399  svntest.actions.run_and_verify_resolved([m], '--depth=files', A)
2400
2401
2402def tree_conflicts_resolved_depth_immediates(sbox):
2403  "tree conflicts resolved depth-immediates"
2404
2405  make_depth_tree_conflicts(sbox)
2406
2407  wc = sbox.wc_dir
2408  j = os.path.join
2409  A = j(wc, 'A')
2410  m =    j(A, 'mu')
2411  B =    j(A, 'B')
2412
2413  svntest.actions.run_and_verify_resolved([m, B], '--depth=immediates', A)
2414
2415
2416def tree_conflicts_resolved_depth_infinity(sbox):
2417  "tree conflicts resolved depth-infinity"
2418
2419  make_depth_tree_conflicts(sbox)
2420
2421  wc = sbox.wc_dir
2422  j = os.path.join
2423  A = j(wc, 'A')
2424  m =    j(A, 'mu')
2425  B =    j(A, 'B')
2426  g =    j(A, 'D', 'gamma')
2427
2428  svntest.actions.run_and_verify_resolved([m, B, g], '--depth=infinity', A)
2429
2430
2431#----------------------------------------------------------------------
2432# list all tests here, starting with None:
2433test_list = [ None,
2434              depth_empty_checkout,
2435              depth_files_checkout,
2436              nonrecursive_checkout,
2437              depth_empty_update_bypass_single_file,
2438              depth_immediates_get_top_file_mod_only,
2439              depth_empty_commit,
2440              depth_empty_with_file,
2441              depth_empty_with_dir,
2442              depth_immediates_bring_in_file,
2443              depth_immediates_fill_in_dir,
2444              depth_mixed_bring_in_dir,
2445              depth_empty_unreceive_delete,
2446              depth_immediates_unreceive_delete,
2447              depth_immediates_receive_delete,
2448              depth_update_to_more_depth,
2449              depth_immediates_subdir_propset_1,
2450              depth_immediates_subdir_propset_2,
2451              commit_propmods_with_depth_empty,
2452              diff_in_depthy_wc,
2453              commit_depth_immediates,
2454              depth_immediates_receive_new_dir,
2455              add_tree_with_depth,
2456              upgrade_from_above,
2457              status_in_depthy_wc,
2458              depthy_update_above_dir_to_be_deleted,
2459              depth_folding_clean_trees_1,
2460              depth_folding_clean_trees_2,
2461              depth_fold_expand_clean_trees,
2462              pull_in_tree_with_depth_option,
2463              fold_tree_with_unversioned_modified_items,
2464              depth_empty_update_on_file,
2465              excluded_path_update_operation,
2466              excluded_path_misc_operation,
2467              excluded_receive_remote_removal,
2468              exclude_keeps_hidden_entries,
2469              tree_conflicts_resolved_depth_empty,
2470              tree_conflicts_resolved_depth_files,
2471              tree_conflicts_resolved_depth_immediates,
2472              tree_conflicts_resolved_depth_infinity,
2473            ]
2474
2475if __name__ == "__main__":
2476  svntest.main.run_tests(test_list)
2477  # NOTREACHED
2478
2479
2480### End of file.
Note: See TracBrowser for help on using the repository browser.