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.apache.org for more information.
9#
10# ====================================================================
11#    Licensed to the Apache Software Foundation (ASF) under one
12#    or more contributor license agreements.  See the NOTICE file
13#    distributed with this work for additional information
14#    regarding copyright ownership.  The ASF licenses this file
15#    to you under the Apache License, Version 2.0 (the
16#    "License"); you may not use this file except in compliance
17#    with the License.  You may obtain a copy of the License at
18#
19#      http://www.apache.org/licenses/LICENSE-2.0
20#
21#    Unless required by applicable law or agreed to in writing,
22#    software distributed under the License is distributed on an
23#    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24#    KIND, either express or implied.  See the License for the
25#    specific language governing permissions and limitations
26#    under the License.
27######################################################################
28
29# General modules
30import os
31import re
32
33# Our testing module
34import svntest
35from svntest import wc
36
37# (abbreviation)
38Skip = svntest.testcase.Skip_deco
39SkipUnless = svntest.testcase.SkipUnless_deco
40XFail = svntest.testcase.XFail_deco
41Issues = svntest.testcase.Issues_deco
42Issue = svntest.testcase.Issue_deco
43Wimp = svntest.testcase.Wimp_deco
44Item = wc.StateItem
45
46# For errors setting up the depthy working copies.
47class DepthSetupError(Exception):
48  def __init__ (self, args=None):
49    self.args = args
50
51def set_up_depthy_working_copies(sbox, empty=False, files=False,
52                                 immediates=False, infinity=False):
53  """Set up up to four working copies, at various depths.  At least
54  one of depths EMPTY, FILES, IMMEDIATES, or INFINITY must be passed
55  as True.  The corresponding working copy paths are returned in a
56  four-element tuple in that order, with element value of None for
57  working copies that were not created.  If all args are False, raise
58  DepthSetupError."""
59
60  if not (infinity or empty or files or immediates):
61    raise DepthSetupError("At least one working copy depth must be passed.")
62
63  wc = None
64  if infinity:
65    sbox.build()
66    wc = sbox.wc_dir
67  else:
68    sbox.build(create_wc = False)
69    sbox.add_test_path(sbox.wc_dir, True)
70
71  wc_empty = None
72  if empty:
73    wc_empty = sbox.wc_dir + '-depth-empty'
74    sbox.add_test_path(wc_empty, True)
75    svntest.actions.run_and_verify_svn(
76      svntest.verify.AnyOutput, [],
77      "co", "--depth", "empty", sbox.repo_url, wc_empty)
78
79  wc_files = None
80  if files:
81    wc_files = sbox.wc_dir + '-depth-files'
82    sbox.add_test_path(wc_files, True)
83    svntest.actions.run_and_verify_svn(
84      svntest.verify.AnyOutput, [],
85      "co", "--depth", "files", sbox.repo_url, wc_files)
86
87  wc_immediates = None
88  if immediates:
89    wc_immediates = sbox.wc_dir + '-depth-immediates'
90    sbox.add_test_path(wc_immediates, True)
91    svntest.actions.run_and_verify_svn(
92      svntest.verify.AnyOutput, [],
93      "co", "--depth", "immediates",
94      sbox.repo_url, wc_immediates)
95
96  return wc_empty, wc_files, wc_immediates, wc
97
98def verify_depth(msg, depth, path="."):
99  """Verifies that PATH has depth DEPTH.  MSG is the failure message."""
100  if depth == "infinity":
101    # Check for absence of depth line.
102    exit_code, out, err = svntest.actions.run_and_verify_svn(None,
103                                                             [], "info", path)
104    for line in out:
105      if line.startswith("Depth:"):
106        raise svntest.Failure(msg)
107  else:
108    expected_stdout = svntest.verify.ExpectedOutput("Depth: %s\n" % depth,
109                                                    match_all=False)
110    svntest.actions.run_and_verify_svn(
111      expected_stdout, [], "info", path)
112
113#----------------------------------------------------------------------
114# Ensure that 'checkout --depth=empty' results in a depth-empty working copy.
115def depth_empty_checkout(sbox):
116  "depth-empty checkout"
117
118  wc_empty, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
119
120  if os.path.exists(os.path.join(wc_empty, "iota")):
121    raise svntest.Failure("depth-empty checkout created file 'iota'")
122
123  if os.path.exists(os.path.join(wc_empty, "A")):
124    raise svntest.Failure("depth-empty checkout created subdir 'A'")
125
126  verify_depth("Expected depth empty for top of WC, got some other depth",
127               "empty", wc_empty)
128
129
130# Helper for two test functions.
131def depth_files_same_as_nonrecursive(sbox, opt):
132  """Run a depth-files or non-recursive checkout, depending on whether
133  passed '-N' or '--depth=files' for OPT.  The two should get the same
134  result, hence this helper containing the common code between the
135  two tests."""
136
137  # This duplicates some code from set_up_depthy_working_copies(), but
138  # that's because it's abstracting out a different axis.
139
140  sbox.build(create_wc = False, read_only = True)
141  if os.path.exists(sbox.wc_dir):
142    svntest.main.safe_rmtree(sbox.wc_dir)
143
144  svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [],
145                                     "co", opt, sbox.repo_url, sbox.wc_dir)
146
147  # Should create a depth-files top directory, so both iota and A
148  # should exist, and A should be empty and depth-empty.
149
150  if not os.path.exists(sbox.ospath('iota')):
151    raise svntest.Failure("'checkout %s' failed to create file 'iota'" % opt)
152
153  if os.path.exists(sbox.ospath('A')):
154    raise svntest.Failure("'checkout %s' unexpectedly created subdir 'A'" % opt)
155
156  verify_depth("Expected depth files for top of WC, got some other depth",
157               "files", sbox.wc_dir)
158
159
160def depth_files_checkout(sbox):
161  "depth-files checkout"
162  depth_files_same_as_nonrecursive(sbox, "--depth=files")
163
164
165def nonrecursive_checkout(sbox):
166  "non-recursive checkout equals depth-files"
167  depth_files_same_as_nonrecursive(sbox, "-N")
168
169
170#----------------------------------------------------------------------
171def depth_empty_update_bypass_single_file(sbox):
172  "update depth-empty wc shouldn't receive file mod"
173
174  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
175                                                            infinity=True)
176
177  iota_path = os.path.join(wc, 'iota')
178  svntest.main.file_append(iota_path, "new text\n")
179
180  # Commit in the "other" wc.
181  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Sending'), })
182  expected_status = svntest.actions.get_virginal_state(wc, 1)
183  expected_status.tweak('iota', wc_rev=2, status='  ')
184  svntest.actions.run_and_verify_commit(wc,
185                                        expected_output,
186                                        expected_status)
187
188  # Update the depth-empty wc, expecting not to receive the change to iota.
189  expected_output = svntest.wc.State(wc_empty, { })
190  expected_disk = svntest.wc.State('', { })
191  expected_status = svntest.wc.State(wc_empty, { '' : svntest.wc.StateItem() })
192  expected_status.tweak(contents=None, status='  ', wc_rev=2)
193  svntest.actions.run_and_verify_update(wc_empty,
194                                        expected_output,
195                                        expected_disk,
196                                        expected_status)
197
198  # And the wc should still be depth-empty.
199  verify_depth(None, "empty", wc_empty)
200
201  # Even if we explicitly ask for a depth-infinity update, we still shouldn't
202  # get the change to iota.
203  svntest.actions.run_and_verify_update(wc_empty,
204                                        expected_output,
205                                        expected_disk,
206                                        expected_status,
207                                        [], False,
208                                        "--depth=infinity", wc_empty)
209
210  # And the wc should still be depth-empty.
211  verify_depth(None, "empty", wc_empty)
212
213
214#----------------------------------------------------------------------
215def depth_immediates_get_top_file_mod_only(sbox):
216  "update depth-immediates wc gets top file mod only"
217
218  ign_a, ign_b, wc_immediates, wc \
219         = set_up_depthy_working_copies(sbox, immediates=True, infinity=True)
220
221  iota_path = os.path.join(wc, 'iota')
222  svntest.main.file_append(iota_path, "new text in iota\n")
223  mu_path = os.path.join(wc, 'A', 'mu')
224  svntest.main.file_append(mu_path, "new text in mu\n")
225
226  # Commit in the "other" wc.
227  expected_output = svntest.wc.State(wc,
228                                     { 'iota' : Item(verb='Sending'),
229                                       'A/mu' : Item(verb='Sending'),
230                                       })
231  expected_status = svntest.actions.get_virginal_state(wc, 1)
232  expected_status.tweak('iota', wc_rev=2, status='  ')
233  expected_status.tweak('A/mu', wc_rev=2, status='  ')
234  svntest.actions.run_and_verify_commit(wc,
235                                        expected_output,
236                                        expected_status)
237
238  # Update the depth-immediates wc, expecting to receive only the
239  # change to iota.
240  expected_output = svntest.wc.State(wc_immediates,
241                                     { 'iota' : Item(status='U ') })
242  expected_disk = svntest.wc.State('', { })
243  expected_disk.add(\
244    {'iota' : Item(contents="This is the file 'iota'.\nnew text in iota\n"),
245     'A' : Item(contents=None) } )
246  expected_status = svntest.wc.State(wc_immediates,
247                                     { '' : svntest.wc.StateItem() })
248  expected_status.tweak(contents=None, status='  ', wc_rev=2)
249  expected_status.add(\
250    {'iota' : Item(status='  ', wc_rev=2),
251     'A' : Item(status='  ', wc_rev=2) } )
252  svntest.actions.run_and_verify_update(wc_immediates,
253                                        expected_output,
254                                        expected_disk,
255                                        expected_status)
256  verify_depth(None, "immediates", wc_immediates)
257
258
259#----------------------------------------------------------------------
260def depth_empty_commit(sbox):
261  "commit a file from a depth-empty working copy"
262  # Bring iota into a depth-empty working copy, then commit a change to it.
263  wc_empty, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox,
264                                                               empty=True)
265
266  # Form the working path of iota
267  wc_empty_iota = os.path.join(wc_empty, 'iota')
268
269  # Update 'iota' in the depth-empty working copy and modify it
270  svntest.actions.run_and_verify_svn(None, [],
271                                     'up', wc_empty_iota)
272  svntest.main.file_write(wc_empty_iota, "iota modified")
273
274  # Commit the modified changes from a depth-empty working copy
275  expected_output = svntest.wc.State(wc_empty, {
276    'iota'        : Item(verb='Sending'),
277    })
278  expected_status = svntest.wc.State(wc_empty, { })
279  expected_status.add({
280    ''            : Item(status='  ', wc_rev=1),
281    'iota'        : Item(status='  ', wc_rev=2),
282    })
283  svntest.actions.run_and_verify_commit(wc_empty,
284                                        expected_output,
285                                        expected_status)
286
287#----------------------------------------------------------------------
288def depth_empty_with_file(sbox):
289  "act on a file in a depth-empty working copy"
290  # Run 'svn up iota' to bring iota permanently into the working copy.
291  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
292                                                            infinity=True)
293
294  iota_path = os.path.join(wc_empty, 'iota')
295  if os.path.exists(iota_path):
296    raise svntest.Failure("'%s' exists when it shouldn't" % iota_path)
297
298  ### I'd love to do this using the recommended {expected_output,
299  ### expected_status, expected_disk} method here, but after twenty
300  ### minutes of trying to figure out how, I decided to compromise.
301
302  # Update iota by name, expecting to receive it.
303  svntest.actions.run_and_verify_svn(None, [], 'up', iota_path)
304
305  # Test that we did receive it.
306  if not os.path.exists(iota_path):
307    raise svntest.Failure("'%s' doesn't exist when it should" % iota_path)
308
309  # Commit a change to iota in the "other" wc.
310  other_iota_path = os.path.join(wc, 'iota')
311  svntest.main.file_append(other_iota_path, "new text\n")
312  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Sending'), })
313  expected_status = svntest.actions.get_virginal_state(wc, 1)
314  expected_status.tweak('iota', wc_rev=2, status='  ')
315  svntest.actions.run_and_verify_commit(wc,
316                                        expected_output,
317                                        expected_status)
318
319  # Delete iota in the "other" wc.
320  other_iota_path = os.path.join(wc, 'iota')
321  svntest.actions.run_and_verify_svn(None, [], 'rm', other_iota_path)
322  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Deleting'), })
323  expected_status = svntest.actions.get_virginal_state(wc, 1)
324  expected_status.remove('iota')
325  svntest.actions.run_and_verify_commit(wc,
326                                        expected_output,
327                                        expected_status)
328
329  # Update the depth-empty wc just a little, expecting to receive
330  # the change in iota.
331  expected_output = svntest.wc.State(\
332    wc_empty, { 'iota' : Item(status='U ') })
333  expected_disk = svntest.wc.State(\
334    '', { 'iota' : Item(contents="This is the file 'iota'.\nnew text\n") })
335  expected_status = svntest.wc.State(wc_empty,
336    { ''     : Item(status='  ', wc_rev=2),
337      'iota' : Item(status='  ', wc_rev=2),})
338  svntest.actions.run_and_verify_update(wc_empty,
339                                        expected_output,
340                                        expected_disk,
341                                        expected_status,
342                                        [], False,
343                                        '-r2', wc_empty)
344
345  # Update the depth-empty wc all the way, expecting to receive the deletion
346  # of iota.
347  expected_output = svntest.wc.State(\
348    wc_empty, { 'iota' : Item(status='D ') })
349  expected_disk = svntest.wc.State('', { })
350  expected_status = svntest.wc.State(\
351    wc_empty, { '' : Item(status='  ', wc_rev=3) })
352  svntest.actions.run_and_verify_update(wc_empty,
353                                        expected_output,
354                                        expected_disk,
355                                        expected_status)
356
357
358#----------------------------------------------------------------------
359def depth_empty_with_dir(sbox):
360  "bring a dir into a depth-empty working copy"
361  # Run 'svn up A' to bring A permanently into the working copy.
362  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
363                                                            infinity=True)
364
365  A_path = os.path.join(wc_empty, 'A')
366  other_mu_path = os.path.join(wc, 'A', 'mu')
367
368  # We expect A to be added at depth infinity, so a normal 'svn up A'
369  # should be sufficient to add all descendants.
370  expected_output = svntest.wc.State(wc_empty, {
371    'A'              : Item(status='A '),
372    'A/mu'           : Item(status='A '),
373    'A/B'            : Item(status='A '),
374    'A/B/lambda'     : Item(status='A '),
375    'A/B/E'          : Item(status='A '),
376    'A/B/E/alpha'    : Item(status='A '),
377    'A/B/E/beta'     : Item(status='A '),
378    'A/B/F'          : Item(status='A '),
379    'A/C'            : Item(status='A '),
380    'A/D'            : Item(status='A '),
381    'A/D/gamma'      : Item(status='A '),
382    'A/D/G'          : Item(status='A '),
383    'A/D/G/pi'       : Item(status='A '),
384    'A/D/G/rho'      : Item(status='A '),
385    'A/D/G/tau'      : Item(status='A '),
386    'A/D/H'          : Item(status='A '),
387    'A/D/H/chi'      : Item(status='A '),
388    'A/D/H/psi'      : Item(status='A '),
389    'A/D/H/omega'    : Item(status='A ')
390    })
391  expected_disk = svntest.main.greek_state.copy()
392  expected_disk.remove('iota')
393  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
394  expected_status.remove('iota')
395  svntest.actions.run_and_verify_update(wc_empty,
396                                        expected_output,
397                                        expected_disk,
398                                        expected_status,
399                                        [], False,
400                                        A_path)
401
402  # Commit a change to A/mu in the "other" wc.
403  svntest.main.file_write(other_mu_path, "new text\n")
404  expected_output = svntest.wc.State(\
405    wc, { 'A/mu' : Item(verb='Sending'), })
406  expected_status = svntest.actions.get_virginal_state(wc, 1)
407  expected_status.tweak('A/mu', wc_rev=2, status='  ')
408  svntest.actions.run_and_verify_commit(wc,
409                                        expected_output,
410                                        expected_status)
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                                        [], False,
425                                        A_path)
426
427  # Commit the deletion of A/mu from the "other" wc.
428  svntest.main.file_write(other_mu_path, "new text\n")
429  svntest.actions.run_and_verify_svn(None, [], 'rm', other_mu_path)
430  expected_output = svntest.wc.State(wc, { 'A/mu' : Item(verb='Deleting'), })
431  expected_status = svntest.actions.get_virginal_state(wc, 1)
432  expected_status.remove('A/mu')
433  svntest.actions.run_and_verify_commit(wc,
434                                        expected_output,
435                                        expected_status)
436
437
438  # Update "A" by name in wc_empty, expect to A/mu to disappear.
439  expected_output = svntest.wc.State(wc_empty, { 'A/mu' : Item(status='D ') })
440  expected_disk = svntest.main.greek_state.copy()
441  expected_disk.remove('iota')
442  expected_disk.remove('A/mu')
443  expected_status = svntest.actions.get_virginal_state(wc_empty, 3)
444  expected_status.remove('iota')
445  expected_status.remove('A/mu')
446  expected_status.tweak('', wc_rev=1)
447  svntest.actions.run_and_verify_update(wc_empty,
448                                        expected_output,
449                                        expected_disk,
450                                        expected_status,
451                                        [], False,
452                                        A_path)
453
454
455
456#----------------------------------------------------------------------
457def depth_immediates_bring_in_file(sbox):
458  "bring a file into a depth-immediates working copy"
459
460  # Create an immediates working copy and form the paths
461  ign_a, ign_b, wc_imm, wc = set_up_depthy_working_copies(sbox,
462                                                          immediates=True)
463  A_mu_path = os.path.join(wc_imm, 'A', 'mu')
464  gamma_path = os.path.join(wc_imm, 'A', 'D', 'gamma')
465
466  # Run 'svn up A/mu' to bring A/mu permanently into the working copy.
467  expected_output = svntest.wc.State(wc_imm, {
468    'A/mu'           : Item(status='A '),
469    })
470  expected_disk = svntest.main.greek_state.copy()
471  expected_disk.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
472                       'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
473                       'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
474                       'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
475  expected_status = svntest.actions.get_virginal_state(wc_imm, 1)
476  expected_status.remove('A/C', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
477                       'A/B/E/beta', 'A/B/F', 'A/B', 'A/D/gamma', 'A/D/G',
478                       'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H/chi',
479                       'A/D/H/psi', 'A/D/H/omega', 'A/D/H', 'A/D')
480  svntest.actions.run_and_verify_update(wc_imm,
481                                        expected_output,
482                                        expected_disk,
483                                        expected_status,
484                                        [], False,
485                                        A_mu_path)
486
487  # Run 'svn up A/D/gamma' to test the edge case 'Skipped'.
488  svntest.actions.run_and_verify_svn(["Skipped '"+gamma_path+"'\n", ],
489                       "svn: E155007: ", 'update', gamma_path)
490  svntest.actions.run_and_verify_status(wc_imm, expected_status)
491
492#----------------------------------------------------------------------
493def depth_immediates_fill_in_dir(sbox):
494  "bring a dir into a depth-immediates working copy"
495
496  # Run 'svn up A --set-depth=infinity' to fill in A as a
497  # depth-infinity subdir.
498  ign_a, ign_b, wc_immediates, wc \
499                        = set_up_depthy_working_copies(sbox, immediates=True)
500  A_path = os.path.join(wc_immediates, 'A')
501  expected_output = svntest.wc.State(wc_immediates, {
502    'A/mu'           : Item(status='A '),
503    'A/B'            : Item(status='A '),
504    'A/B/lambda'     : Item(status='A '),
505    'A/B/E'          : Item(status='A '),
506    'A/B/E/alpha'    : Item(status='A '),
507    'A/B/E/beta'     : Item(status='A '),
508    'A/B/F'          : Item(status='A '),
509    'A/C'            : Item(status='A '),
510    'A/D'            : Item(status='A '),
511    'A/D/gamma'      : Item(status='A '),
512    'A/D/G'          : Item(status='A '),
513    'A/D/G/pi'       : Item(status='A '),
514    'A/D/G/rho'      : Item(status='A '),
515    'A/D/G/tau'      : Item(status='A '),
516    'A/D/H'          : Item(status='A '),
517    'A/D/H/chi'      : Item(status='A '),
518    'A/D/H/psi'      : Item(status='A '),
519    'A/D/H/omega'    : Item(status='A ')
520    })
521  expected_disk = svntest.main.greek_state.copy()
522  expected_status = svntest.actions.get_virginal_state(wc_immediates, 1)
523  svntest.actions.run_and_verify_update(wc_immediates,
524                                        expected_output,
525                                        expected_disk,
526                                        expected_status,
527                                        [], False,
528                                        '--set-depth', 'infinity',
529                                        A_path)
530
531#----------------------------------------------------------------------
532def depth_mixed_bring_in_dir(sbox):
533  "bring a dir into a mixed-depth working copy"
534
535  # Run 'svn up --set-depth=immediates A' in a depth-empty working copy.
536  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True)
537  A_path = os.path.join(wc_empty, 'A')
538  B_path = os.path.join(wc_empty, 'A', 'B')
539  C_path = os.path.join(wc_empty, 'A', 'C')
540
541  expected_output = svntest.wc.State(wc_empty, {
542    'A'              : Item(status='A '),
543    'A/mu'           : Item(status='A '),
544    })
545  expected_disk = svntest.main.greek_state.copy()
546  expected_disk.remove('iota', 'A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
547                       'A/B/E/beta', 'A/B/F', 'A/C', 'A/D', 'A/D/gamma',
548                       'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
549                       'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
550  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
551  expected_status.remove('iota', 'A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/alpha',
552                         'A/B/E/beta', 'A/B/F', 'A/C', 'A/D', 'A/D/gamma',
553                         'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
554                         'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
555  svntest.actions.run_and_verify_update(wc_empty,
556                                        expected_output,
557                                        expected_disk,
558                                        expected_status,
559                                        [], False,
560                                        '--set-depth', 'files',
561                                        A_path)
562  # Check that A was added at depth=files.
563  verify_depth(None, "files", A_path)
564
565  # Now, bring in A/B at depth-immediates.
566  expected_output = svntest.wc.State(wc_empty, {
567    'A/B'            : Item(status='A '),
568    'A/B/lambda'     : Item(status='A '),
569    'A/B/E'          : Item(status='A '),
570    'A/B/F'          : Item(status='A '),
571    })
572  expected_disk = svntest.main.greek_state.copy()
573  expected_disk.remove('iota', 'A/B/E/alpha', 'A/B/E/beta', 'A/C',
574                       'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
575                       'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
576                       'A/D/H/omega')
577  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
578  expected_status.remove('iota', 'A/B/E/alpha', 'A/B/E/beta', 'A/C',
579                         'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
580                         'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
581                         'A/D/H/omega')
582  svntest.actions.run_and_verify_update(wc_empty,
583                                        expected_output,
584                                        expected_disk,
585                                        expected_status,
586                                        [], False,
587                                        '--set-depth', 'immediates',
588                                        B_path)
589  # Check that A/B was added at depth=immediates.
590  verify_depth(None, "immediates", B_path)
591
592  # Now, bring in A/C at depth-empty.
593  expected_output = svntest.wc.State(wc_empty, {
594    'A/C'            : Item(status='A '),
595    })
596  expected_disk = svntest.main.greek_state.copy()
597  expected_disk.remove('iota', 'A/B/E/alpha', 'A/B/E/beta',
598                       'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
599                       'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
600                       'A/D/H/omega')
601  expected_status = svntest.actions.get_virginal_state(wc_empty, 1)
602  expected_status.remove('iota', 'A/B/E/alpha', 'A/B/E/beta',
603                         'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho',
604                         'A/D/G/tau', 'A/D/H', 'A/D/H/chi', 'A/D/H/psi',
605                         'A/D/H/omega')
606  svntest.actions.run_and_verify_update(wc_empty,
607                                        expected_output,
608                                        expected_disk,
609                                        expected_status,
610                                        [], False,
611                                        '--set-depth', 'empty',
612                                        C_path)
613  # Check that A/C was added at depth=empty.
614  verify_depth(None, "empty", C_path)
615
616#----------------------------------------------------------------------
617def depth_empty_unreceive_delete(sbox):
618  "depth-empty working copy ignores a deletion"
619  # Check out a depth-empty greek tree to wc1.  In wc2, delete iota and
620  # commit.  Update wc1; should not receive the delete.
621  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
622                                                            infinity=True)
623
624  iota_path = os.path.join(wc, 'iota')
625
626  # Commit in the "other" wc.
627  svntest.actions.run_and_verify_svn(None, [], 'rm', iota_path)
628  expected_output = svntest.wc.State(wc, { 'iota' : Item(verb='Deleting'), })
629  expected_status = svntest.actions.get_virginal_state(wc, 1)
630  expected_status.remove('iota')
631  svntest.actions.run_and_verify_commit(wc,
632                                        expected_output,
633                                        expected_status)
634
635  # Update the depth-empty wc, expecting not to receive the deletion of iota.
636  expected_output = svntest.wc.State(wc_empty, { })
637  expected_disk = svntest.wc.State('', { })
638  expected_status = svntest.wc.State(wc_empty, { '' : svntest.wc.StateItem() })
639  expected_status.tweak(contents=None, status='  ', wc_rev=2)
640  svntest.actions.run_and_verify_update(wc_empty,
641                                        expected_output,
642                                        expected_disk,
643                                        expected_status)
644
645
646#----------------------------------------------------------------------
647def depth_immediates_unreceive_delete(sbox):
648  "depth-immediates working copy ignores a deletion"
649  # Check out a depth-immediates greek tree to wc1.  In wc2, delete
650  # A/mu and commit.  Update wc1; should not receive the delete.
651
652  ign_a, ign_b, wc_immed, wc = set_up_depthy_working_copies(sbox,
653                                                            immediates=True,
654                                                            infinity=True)
655
656  mu_path = os.path.join(wc, 'A', 'mu')
657
658  # Commit in the "other" wc.
659  svntest.actions.run_and_verify_svn(None, [], 'rm', mu_path)
660  expected_output = svntest.wc.State(wc, { 'A/mu' : Item(verb='Deleting'), })
661  expected_status = svntest.actions.get_virginal_state(wc, 1)
662  expected_status.remove('A/mu')
663  svntest.actions.run_and_verify_commit(wc,
664                                        expected_output,
665                                        expected_status)
666
667  # Update the depth-immediates wc, expecting not to receive the deletion
668  # of A/mu.
669  expected_output = svntest.wc.State(wc_immed, { })
670  expected_disk = svntest.wc.State('', {
671    'iota' : Item(contents="This is the file 'iota'.\n"),
672    'A' : Item()
673    })
674  expected_status = svntest.wc.State(wc_immed, {
675    '' : Item(status='  ', wc_rev=2),
676    'iota' : Item(status='  ', wc_rev=2),
677    'A' : Item(status='  ', wc_rev=2)
678    })
679  svntest.actions.run_and_verify_update(wc_immed,
680                                        expected_output,
681                                        expected_disk,
682                                        expected_status)
683
684#----------------------------------------------------------------------
685def depth_immediates_receive_delete(sbox):
686  "depth-immediates working copy receives a deletion"
687  # Check out a depth-immediates greek tree to wc1.  In wc2, delete A and
688  # commit.  Update wc1  should receive the delete.
689
690  ign_a, ign_b, wc_immed, wc = set_up_depthy_working_copies(sbox,
691                                                            immediates=True,
692                                                            infinity=True)
693
694  A_path = os.path.join(wc, 'A')
695
696  # Commit in the "other" wc.
697  svntest.actions.run_and_verify_svn(None, [], 'rm', A_path)
698  expected_output = svntest.wc.State(wc, { 'A' : Item(verb='Deleting'), })
699  expected_status = svntest.wc.State(wc, {
700    '' : Item(status='  ', wc_rev=1),
701    'iota' : Item(status='  ', wc_rev=1),
702    })
703  svntest.actions.run_and_verify_commit(wc,
704                                        expected_output,
705                                        expected_status)
706
707  # Update the depth-immediates wc, expecting to receive the deletion of A.
708  expected_output = svntest.wc.State(wc_immed, {
709    'A'    : Item(status='D ')
710    })
711  expected_disk = svntest.wc.State('', {
712    'iota' : Item(contents="This is the file 'iota'.\n"),
713    })
714  expected_status = svntest.wc.State(wc_immed, {
715    ''     : Item(status='  ', wc_rev=2),
716    'iota' : Item(status='  ', wc_rev=2)
717    })
718  svntest.actions.run_and_verify_update(wc_immed,
719                                        expected_output,
720                                        expected_disk,
721                                        expected_status)
722
723#----------------------------------------------------------------------
724def depth_immediates_subdir_propset_1(sbox):
725  "depth-immediates commit subdir propset, update"
726  ign_a, ign_b, wc_immediates, ign_c \
727         = set_up_depthy_working_copies(sbox, immediates=True)
728
729  A_path = os.path.join(wc_immediates, 'A')
730
731  # Set a property on an immediate subdirectory of the working copy.
732  svntest.actions.run_and_verify_svn(None, [],
733                                     'pset', 'foo', 'bar',
734                                     A_path)
735
736  # Create expected output tree.
737  expected_output = svntest.wc.State(wc_immediates, {
738    'A' : Item(verb='Sending'),
739    })
740
741  # Create expected status tree.
742  expected_status = svntest.wc.State(wc_immediates, {
743    '' : Item(status='  ', wc_rev=1),
744    'iota' : Item(status='  ', wc_rev=1),
745    'A' : Item(status='  ', wc_rev=2)
746    })
747
748  # Commit wc_immediates/A.
749  svntest.actions.run_and_verify_commit(wc_immediates,
750                                        expected_output,
751                                        expected_status,
752                                        [],
753                                        A_path)
754
755  # Create expected output tree for the update.
756  expected_output = svntest.wc.State(wc_immediates, { })
757
758  # Create expected disk tree.
759  expected_disk = svntest.wc.State('', {
760    'iota' : Item(contents="This is the file 'iota'.\n"),
761    'A' : Item(contents=None, props={'foo' : 'bar'}),
762    })
763
764  expected_status.tweak(contents=None, status='  ', wc_rev=2)
765
766  # Update the depth-immediates wc.
767  svntest.actions.run_and_verify_update(wc_immediates,
768                                        expected_output,
769                                        expected_disk,
770                                        expected_status,
771                                        check_props=True)
772
773#----------------------------------------------------------------------
774def depth_immediates_subdir_propset_2(sbox):
775  "depth-immediates update receives subdir propset"
776  sbox.build()
777  wc_dir = sbox.wc_dir
778
779  # Make the other working copy.
780  other_wc = sbox.add_wc_path('other')
781  svntest.actions.duplicate_dir(wc_dir, other_wc)
782
783  A_path = sbox.ospath('A')
784
785  # Set a property on an immediate subdirectory of the working copy.
786  svntest.actions.run_and_verify_svn(None, [],
787                                     'pset', 'foo', 'bar',
788                                     A_path)
789  # Commit.
790  svntest.actions.run_and_verify_svn(None, [],
791                                     'commit', '-m', 'logmsg', A_path)
792
793  # Update at depth=immediates in the other wc, expecting to see no errors.
794  svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [],
795                                     'update', '--depth', 'immediates',
796                                     other_wc)
797
798#----------------------------------------------------------------------
799def depth_update_to_more_depth(sbox):
800  "gradually update an empty wc to depth=infinity"
801
802  wc_dir, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
803
804  os.chdir(wc_dir)
805
806  # Run 'svn up --set-depth=files' in a depth-empty working copy.
807  expected_output = svntest.wc.State('', {
808    'iota'              : Item(status='A '),
809    })
810  expected_status = svntest.wc.State('', {
811    '' : Item(status='  ', wc_rev=1),
812    'iota' : Item(status='  ', wc_rev=1),
813    })
814  expected_disk = svntest.wc.State('', {
815    'iota' : Item("This is the file 'iota'.\n"),
816    })
817  svntest.actions.run_and_verify_update('',
818                                        expected_output,
819                                        expected_disk,
820                                        expected_status,
821                                        [], False,
822                                        '--set-depth', 'files')
823  verify_depth(None, "files")
824
825  # Run 'svn up --set-depth=immediates' in the now depth-files working copy.
826  expected_output = svntest.wc.State('', {
827    'A'              : Item(status='A '),
828    })
829  expected_status = svntest.wc.State('', {
830    '' : Item(status='  ', wc_rev=1),
831    'iota' : Item(status='  ', wc_rev=1),
832    'A' : Item(status='  ', wc_rev=1),
833    })
834  expected_disk = svntest.wc.State('', {
835    'iota' : Item("This is the file 'iota'.\n"),
836    'A'    : Item(),
837    })
838  svntest.actions.run_and_verify_update('',
839                                        expected_output,
840                                        expected_disk,
841                                        expected_status,
842                                        [], False,
843                                        '--set-depth', 'immediates')
844  verify_depth(None, "immediates")
845  verify_depth(None, "empty", "A")
846
847  # Upgrade 'A' to depth-files.
848  expected_output = svntest.wc.State('', {
849    'A/mu'           : Item(status='A '),
850    })
851  expected_status = svntest.wc.State('', {
852    '' : Item(status='  ', wc_rev=1),
853    'iota' : Item(status='  ', wc_rev=1),
854    'A' : Item(status='  ', wc_rev=1),
855    'A/mu' : Item(status='  ', wc_rev=1),
856    })
857  expected_disk = svntest.wc.State('', {
858    'iota' : Item("This is the file 'iota'.\n"),
859    'A'    : Item(),
860    'A/mu' : Item("This is the file 'mu'.\n"),
861    })
862  svntest.actions.run_and_verify_update('',
863                                        expected_output,
864                                        expected_disk,
865                                        expected_status,
866                                        [], False,
867                                        '--set-depth', 'files', 'A')
868  verify_depth(None, "immediates")
869  verify_depth(None, "files", "A")
870
871  # Run 'svn up --set-depth=infinity' in the working copy.
872  expected_output = svntest.wc.State('', {
873    'A/B'            : Item(status='A '),
874    'A/B/lambda'     : Item(status='A '),
875    'A/B/E'          : Item(status='A '),
876    'A/B/E/alpha'    : Item(status='A '),
877    'A/B/E/beta'     : Item(status='A '),
878    'A/B/F'          : Item(status='A '),
879    'A/C'            : Item(status='A '),
880    'A/D'            : Item(status='A '),
881    'A/D/gamma'      : Item(status='A '),
882    'A/D/G'          : Item(status='A '),
883    'A/D/G/pi'       : Item(status='A '),
884    'A/D/G/rho'      : Item(status='A '),
885    'A/D/G/tau'      : Item(status='A '),
886    'A/D/H'          : Item(status='A '),
887    'A/D/H/chi'      : Item(status='A '),
888    'A/D/H/psi'      : Item(status='A '),
889    'A/D/H/omega'    : Item(status='A ')
890    })
891  expected_disk = svntest.main.greek_state.copy()
892  expected_status = svntest.actions.get_virginal_state('', 1)
893  svntest.actions.run_and_verify_update('',
894                                        expected_output,
895                                        expected_disk,
896                                        expected_status,
897                                        [], False,
898                                        '--set-depth', 'infinity')
899  verify_depth("Non-infinity depth detected after an upgrade to depth-infinity",
900               "infinity")
901  verify_depth("Non-infinity depth detected after an upgrade to depth-infinity",
902               "infinity", "A")
903
904def commit_propmods_with_depth_empty_helper(sbox, depth_arg):
905  """Helper for commit_propmods_with_depth_empty().
906  DEPTH_ARG should be either '--depth=empty' or '-N'."""
907
908  sbox.build()
909  wc_dir = sbox.wc_dir
910
911  iota_path = sbox.ospath('iota')
912  A_path = sbox.ospath('A')
913  D_path = os.path.join(A_path, 'D')
914  gamma_path = os.path.join(D_path, 'gamma')
915  G_path = os.path.join(D_path, 'G')
916  pi_path = os.path.join(G_path, 'pi')
917  H_path = os.path.join(D_path, 'H')
918  chi_path = os.path.join(H_path, 'chi')
919
920  # Set some properties, modify some files.
921  svntest.actions.run_and_verify_svn(None, [],
922                                     'propset', 'foo', 'foo-val', wc_dir)
923  svntest.actions.run_and_verify_svn(None, [],
924                                     'propset', 'bar', 'bar-val', D_path)
925  svntest.actions.run_and_verify_svn(None, [],
926                                     'propset', 'baz', 'baz-val', G_path)
927  svntest.actions.run_and_verify_svn(None, [],
928                                     'propset', 'qux', 'qux-val', H_path)
929  svntest.main.file_append(iota_path, "new iota\n")
930  svntest.main.file_append(gamma_path, "new gamma\n")
931  svntest.main.file_append(pi_path, "new pi\n")
932  svntest.main.file_append(chi_path, "new chi\n")
933
934  # The only things that should be committed are two of the propsets.
935  expected_output = svntest.wc.State(
936    wc_dir,
937    { ''    : Item(verb='Sending'),
938      'A/D' : Item(verb='Sending'), }
939    )
940  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
941  # Expect the two propsets to be committed:
942  expected_status.tweak('', status='  ', wc_rev=2)
943  expected_status.tweak('A/D', status='  ', wc_rev=2)
944  # Expect every other change to remain uncommitted:
945  expected_status.tweak('iota', status='M ', wc_rev=1)
946  expected_status.tweak('A/D/G', status=' M', wc_rev=1)
947  expected_status.tweak('A/D/H', status=' M', wc_rev=1)
948  expected_status.tweak('A/D/gamma', status='M ', wc_rev=1)
949  expected_status.tweak('A/D/G/pi', status='M ', wc_rev=1)
950  expected_status.tweak('A/D/H/chi', status='M ', wc_rev=1)
951
952  svntest.actions.run_and_verify_commit(wc_dir,
953                                        expected_output,
954                                        expected_status,
955                                        [],
956                                        depth_arg,
957                                        wc_dir, D_path)
958
959# See also commit_tests 26: commit_nonrecursive
960def commit_propmods_with_depth_empty(sbox):
961  "commit property mods only, using --depth=empty"
962
963  sbox2 = sbox.clone_dependent()
964
965  # Run once with '-N' and once with '--depth=empty' to make sure they
966  # function identically.
967  commit_propmods_with_depth_empty_helper(sbox, '-N')
968  commit_propmods_with_depth_empty_helper(sbox2, '--depth=empty')
969
970# Test for issue #2845.
971@Issue(2845)
972def diff_in_depthy_wc(sbox):
973  "diff at various depths in non-infinity wc"
974
975  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
976                                                            infinity=True)
977
978  iota_path = os.path.join(wc, 'iota')
979  A_path = os.path.join(wc, 'A')
980  mu_path = os.path.join(wc, 'A', 'mu')
981  gamma_path = os.path.join(wc, 'A', 'D', 'gamma')
982
983  # Make some changes in the depth-infinity wc, and commit them
984  svntest.actions.run_and_verify_svn(None, [],
985                                     'propset', 'foo', 'foo-val', wc)
986  svntest.main.file_write(iota_path, "new text\n")
987  svntest.actions.run_and_verify_svn(None, [],
988                                     'propset', 'bar', 'bar-val', A_path)
989  svntest.main.file_write(mu_path, "new text\n")
990  svntest.main.file_write(gamma_path, "new text\n")
991  svntest.actions.run_and_verify_svn(None, [],
992                                     'commit', '-m', '', wc)
993
994  from svntest.verify import make_diff_header, make_diff_prop_header, \
995                             make_diff_prop_deleted, make_diff_prop_added
996  diff_mu = make_diff_header('A/mu', 'revision 2', 'working copy') + [
997    "@@ -1 +1 @@\n",
998    "-new text\n",
999    "+This is the file 'mu'.\n"]
1000  diff_A = make_diff_header('A', 'revision 2', 'working copy') + \
1001           make_diff_prop_header('A') + \
1002           make_diff_prop_deleted('bar', 'bar-val')
1003  diff_iota = make_diff_header('iota', 'revision 2', 'working copy') + [
1004    "@@ -1 +1 @@\n",
1005    "-new text\n",
1006    "+This is the file 'iota'.\n"]
1007  diff_dot = make_diff_header('.', 'revision 2', 'working copy') + \
1008             make_diff_prop_header('.') + \
1009             make_diff_prop_deleted('foo', 'foo-val')
1010
1011  os.chdir(wc_empty)
1012
1013  expected_output = svntest.verify.UnorderedOutput(diff_dot)
1014  # The diff should contain only the propchange on '.'
1015  svntest.actions.run_and_verify_svn(expected_output, [],
1016                                     'diff', '-rHEAD')
1017
1018  # Upgrade to depth-files.
1019  svntest.actions.run_and_verify_svn(None, [], 'up',
1020                                     '--set-depth', 'files', '-r1')
1021  # The diff should contain only the propchange on '.' and the
1022  # contents change on iota.
1023  expected_output = svntest.verify.UnorderedOutput(diff_iota + diff_dot)
1024  svntest.actions.run_and_verify_svn(expected_output, [],
1025                                     'diff', '-rHEAD')
1026  # Do a diff at --depth empty.
1027  expected_output = svntest.verify.UnorderedOutput(diff_dot)
1028  svntest.actions.run_and_verify_svn(expected_output, [],
1029                                     'diff', '--depth', 'empty', '-rHEAD')
1030
1031  # Upgrade to depth-immediates.
1032  svntest.actions.run_and_verify_svn(None, [], 'up',
1033                                     '--set-depth', 'immediates', '-r1')
1034  # The diff should contain the propchanges on '.' and 'A' and the
1035  # contents change on iota.
1036  expected_output = svntest.verify.UnorderedOutput(diff_A + diff_iota +
1037                                                   diff_dot)
1038  svntest.actions.run_and_verify_svn(expected_output, [],
1039                                    'diff', '-rHEAD')
1040  # Do a diff at --depth files.
1041  expected_output = svntest.verify.UnorderedOutput(diff_iota + diff_dot)
1042  svntest.actions.run_and_verify_svn(expected_output, [],
1043                                     'diff', '--depth', 'files', '-rHEAD')
1044
1045  # Upgrade A to depth-files.
1046  svntest.actions.run_and_verify_svn(None, [], 'up',
1047                                     '--set-depth', 'files', '-r1', 'A')
1048  # The diff should contain everything but the contents change on
1049  # gamma (which does not exist in this working copy).
1050  expected_output = svntest.verify.UnorderedOutput(diff_mu + diff_A +
1051                                                   diff_iota + diff_dot)
1052  svntest.actions.run_and_verify_svn(expected_output, [],
1053                                     'diff', '-rHEAD')
1054  # Do a diff at --depth immediates.
1055  expected_output = svntest.verify.UnorderedOutput(diff_A + diff_iota +                                                                                diff_dot)
1056  svntest.actions.run_and_verify_svn(expected_output, [],
1057                                    'diff', '--depth', 'immediates', '-rHEAD')
1058
1059@Issue(2882)
1060def commit_depth_immediates(sbox):
1061  "commit some files with --depth=immediates"
1062  sbox.build()
1063  wc_dir = sbox.wc_dir
1064
1065  # Test the fix for some bugs Mike Pilato reported here:
1066  #
1067  #    http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=128509
1068  #    From: "C. Michael Pilato" <cmpilato@collab.net>
1069  #    To: Karl Fogel <kfogel@red-bean.com>
1070  #    CC: dev@subversion.tigris.org
1071  #    References: <87d4yzcrro.fsf@red-bean.com>
1072  #    Subject: Re: [PATCH] Make 'svn commit --depth=foo' work.
1073  #    Message-ID: <46968831.2070906@collab.net>
1074  #    Date: Thu, 12 Jul 2007 15:59:45 -0400
1075  #
1076  # See also https://issues.apache.org/jira/browse/SVN-2882.
1077  #
1078  # Outline of the test:
1079  # ====================
1080  #
1081  # Modify these three files:
1082  #
1083  #    M      A/mu
1084  #    M      A/D/G/rho
1085  #    M      iota
1086  #
1087  # Then commit some of them using --depth=immediates:
1088  #
1089  #    svn ci -m "log msg" --depth=immediates wc_dir wc_dir/A/D/G/rho
1090  #
1091  # Before the bugfix, that would result in an error:
1092  #
1093  #    subversion/libsvn_wc/lock.c:570: (apr_err=155004)
1094  #    svn: Working copy '/blah/blah/blah/wc' locked
1095  #    svn: run 'svn cleanup' to remove locks \
1096  #         (type 'svn help cleanup' for details)
1097  #
1098  # After the bugfix, it correctly commits two of the three files:
1099  #
1100  #    Sending        A/D/G/rho
1101  #    Sending        iota
1102  #    Transmitting file data ..
1103  #    Committing transaction...
1104  #    Committed revision 2.
1105
1106  iota_path = sbox.ospath('iota')
1107  mu_path   = sbox.ospath('A/mu')
1108  G_path    = sbox.ospath('A/D/G')
1109  rho_path  = os.path.join(G_path, 'rho')
1110
1111  svntest.main.file_append(iota_path, "new text in iota\n")
1112  svntest.main.file_append(mu_path,   "new text in mu\n")
1113  svntest.main.file_append(rho_path,  "new text in rho\n")
1114
1115  expected_output = svntest.wc.State(wc_dir, {
1116    'iota' : Item(verb='Sending'),
1117    'A/D/G/rho' : Item(verb='Sending'),
1118    })
1119  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1120  expected_status.tweak('iota',       status='  ',  wc_rev=2)
1121  expected_status.tweak('A/mu',       status='M ',  wc_rev=1)
1122  expected_status.tweak('A/D/G/rho',  status='  ',  wc_rev=2)
1123  svntest.actions.run_and_verify_commit(wc_dir,
1124                                        expected_output,
1125                                        expected_status,
1126                                        [],
1127                                        '--depth', 'immediates',
1128                                        wc_dir, G_path)
1129
1130def depth_immediates_receive_new_dir(sbox):
1131  "depth-immediates wc receives new directory"
1132
1133  ign_a, ign_b, wc_immed, wc = set_up_depthy_working_copies(sbox,
1134                                                            immediates=True,
1135                                                            infinity=True)
1136
1137  I_path = os.path.join(wc, 'I')
1138  zeta_path = os.path.join(wc, 'I', 'zeta')
1139  other_I_path = os.path.join(wc_immed, 'I')
1140
1141  os.mkdir(I_path)
1142  svntest.main.file_write(zeta_path, "This is the file 'zeta'.\n")
1143
1144  # Commit in the "other" wc.
1145  svntest.actions.run_and_verify_svn(None, [], 'add', I_path)
1146  expected_output = svntest.wc.State(wc, {
1147    'I'      : Item(verb='Adding'),
1148    'I/zeta' : Item(verb='Adding'),
1149    })
1150  expected_status = svntest.actions.get_virginal_state(wc, 1)
1151  expected_status.add({
1152    'I'      : Item(status='  ', wc_rev=2),
1153    'I/zeta' : Item(status='  ', wc_rev=2),
1154    })
1155  svntest.actions.run_and_verify_commit(wc,
1156                                        expected_output,
1157                                        expected_status)
1158
1159  # Update the depth-immediates wc, expecting to receive just the
1160  # new directory, without the file.
1161  expected_output = svntest.wc.State(wc_immed, {
1162    'I'    : Item(status='A '),
1163    })
1164  expected_disk = svntest.wc.State('', {
1165    'iota' : Item(contents="This is the file 'iota'.\n"),
1166    'A'    : Item(),
1167    'I'    : Item(),
1168    })
1169  expected_status = svntest.wc.State(wc_immed, {
1170    ''     : Item(status='  ', wc_rev=2),
1171    'iota' : Item(status='  ', wc_rev=2),
1172    'A'    : Item(status='  ', wc_rev=2),
1173    'I'    : Item(status='  ', wc_rev=2),
1174    })
1175  svntest.actions.run_and_verify_update(wc_immed,
1176                                        expected_output,
1177                                        expected_disk,
1178                                        expected_status)
1179  # Check that the new directory was added at depth=empty.
1180  verify_depth(None, "empty", other_I_path)
1181
1182@Issue(2931)
1183def add_tree_with_depth(sbox):
1184  "add multi-subdir tree with --depth options"  # For issue #2931
1185  sbox.build()
1186  wc_dir = sbox.wc_dir
1187  new1_path = sbox.ospath('new1')
1188  new2_path = os.path.join(new1_path, 'new2')
1189  new3_path = os.path.join(new2_path, 'new3')
1190  new4_path = os.path.join(new3_path, 'new4')
1191  os.mkdir(new1_path)
1192  os.mkdir(new2_path)
1193  os.mkdir(new3_path)
1194  os.mkdir(new4_path)
1195  # Simple case, add new1 only, set depth to files
1196  svntest.actions.run_and_verify_svn(None, [],
1197                                     "add", "--depth", "files", new1_path)
1198  verify_depth(None, "infinity", new1_path)
1199
1200  # Force add new1 at new1 again, should include new2 at empty, the depth of
1201  # new1 should not change
1202  svntest.actions.run_and_verify_svn(None, [],
1203                                     "add", "--depth", "immediates",
1204                                     "--force", new1_path)
1205  verify_depth(None, "infinity", new1_path)
1206  verify_depth(None, "infinity", new2_path)
1207
1208  # add new4 with intermediate path, the intermediate path is added at empty
1209  svntest.actions.run_and_verify_svn(None, [],
1210                                     "add", "--depth", "immediates",
1211                                     "--parents", new4_path)
1212  verify_depth(None, "infinity", new3_path)
1213  verify_depth(None, "infinity", new4_path)
1214
1215def upgrade_from_above(sbox):
1216  "upgrade a depth=empty wc from above"
1217
1218  # The bug was that 'svn up --set-depth=files' worked from within the
1219  # working copy, but not from without with working copy top given
1220  # as an argument.  Both ways would correctly cause 'iota' to
1221  # appear, but only the former actually upgraded the depth of the
1222  # working copy to 'files'.  See this thread for details:
1223  #
1224  #   http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=130157
1225  #   From: Alexander Sinyushkin <Alexander.Sinyushkin@svnkit.com>
1226  #   To: dev@subversion.tigris.org
1227  #   Subject: Problem upgrading working copy depth
1228  #   Date: Wed, 19 Sep 2007 23:15:24 +0700
1229  #   Message-ID: <46F14B1C.8010406@svnkit.com>
1230
1231  sbox2 = sbox.clone_dependent()
1232
1233  wc, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
1234
1235  # First verify that upgrading from within works.
1236  saved_cwd = os.getcwd()
1237  try:
1238    os.chdir(wc)
1239    expected_output = svntest.wc.State('', {
1240        'iota'    : Item(status='A '),
1241        })
1242    expected_disk = svntest.wc.State('', {
1243        'iota' : Item(contents="This is the file 'iota'.\n"),
1244        })
1245    expected_status = svntest.wc.State('', {
1246        ''     : Item(status='  ', wc_rev=1),
1247        'iota' : Item(status='  ', wc_rev=1),
1248        })
1249    svntest.actions.run_and_verify_update('',
1250                                          expected_output,
1251                                          expected_disk,
1252                                          expected_status,
1253                                          [], False,
1254                                          '--set-depth=files', '.')
1255    verify_depth(None, "files")
1256  finally:
1257    os.chdir(saved_cwd)
1258
1259  # Do it again, this time from above the working copy.
1260  wc, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox2, empty=True)
1261  expected_output = svntest.wc.State(wc, {
1262      'iota'    : Item(status='A '),
1263      })
1264  expected_disk = svntest.wc.State('', {
1265      'iota' : Item(contents="This is the file 'iota'.\n"),
1266      })
1267  expected_status = svntest.wc.State(wc, {
1268      ''     : Item(status='  ', wc_rev=1),
1269      'iota' : Item(status='  ', wc_rev=1),
1270      })
1271  svntest.actions.run_and_verify_update(wc,
1272                                        expected_output,
1273                                        expected_disk,
1274                                        expected_status,
1275                                        [], False,
1276                                        '--set-depth=files', wc)
1277  verify_depth(None, "files", wc)
1278
1279def status_in_depthy_wc(sbox):
1280  "status -u at various depths in non-infinity wc"
1281
1282  wc_empty, ign_a, ign_b, wc = set_up_depthy_working_copies(sbox, empty=True,
1283                                                            infinity=True)
1284
1285  iota_path = os.path.join(wc, 'iota')
1286  A_path = os.path.join(wc, 'A')
1287  mu_path = os.path.join(wc, 'A', 'mu')
1288  gamma_path = os.path.join(wc, 'A', 'D', 'gamma')
1289
1290  # Make some changes in the depth-infinity wc, and commit them
1291  svntest.actions.run_and_verify_svn(None, [],
1292                                     'propset', 'foo', 'foo-val', wc)
1293  svntest.main.file_write(iota_path, "new text\n")
1294  svntest.actions.run_and_verify_svn(None, [],
1295                                     'propset', 'bar', 'bar-val', A_path)
1296  svntest.main.file_write(mu_path, "new text\n")
1297  svntest.main.file_write(gamma_path, "new text\n")
1298  svntest.actions.run_and_verify_svn(None, [],
1299                                     'commit', '-m', '', wc)
1300
1301  status = [
1302    "Status against revision:      2\n",
1303    "        *        1   .\n",
1304    "        *        1   iota\n",
1305    "        *        1   A\n",
1306    "        *        1   " + os.path.join('A', 'mu') + "\n",
1307  ]
1308
1309  os.chdir(wc_empty)
1310
1311  expected_output = svntest.verify.UnorderedOutput(status[:2])
1312  # The output should contain only the change on '.'.
1313  svntest.actions.run_and_verify_svn(expected_output, [],
1314                                     'st', '-u')
1315
1316  # Upgrade to depth-files.
1317  svntest.actions.run_and_verify_svn(None, [], 'up',
1318                                     '--set-depth', 'files', '-r1')
1319  # The output should contain only the changes on '.' and 'iota'.
1320  expected_output = svntest.verify.UnorderedOutput(status[:3])
1321  svntest.actions.run_and_verify_svn(expected_output, [],
1322                                     'st', '-u')
1323  # Do a status -u at --depth empty.
1324  expected_output = svntest.verify.UnorderedOutput(status[:2])
1325  svntest.actions.run_and_verify_svn(expected_output, [],
1326                                     'st', '-u', '--depth', 'empty')
1327
1328  # Upgrade to depth-immediates.
1329  svntest.actions.run_and_verify_svn(None, [], 'up',
1330                                     '--set-depth', 'immediates', '-r1')
1331  # The output should contain the changes on '.', 'A' and 'iota'.
1332  expected_output = svntest.verify.UnorderedOutput(status[:4])
1333  svntest.actions.run_and_verify_svn(expected_output, [],
1334                                    'st', '-u')
1335  # Do a status -u at --depth files.
1336  expected_output = svntest.verify.UnorderedOutput(status[:3])
1337  svntest.actions.run_and_verify_svn(expected_output, [],
1338                                     'st', '-u', '--depth', 'files')
1339
1340  # Upgrade A to depth-files.
1341  svntest.actions.run_and_verify_svn(None, [], 'up',
1342                                     '--set-depth', 'files', '-r1', 'A')
1343  # The output should contain everything but the change on
1344  # gamma (which does not exist in this working copy).
1345  expected_output = svntest.verify.UnorderedOutput(status)
1346  svntest.actions.run_and_verify_svn(expected_output, [],
1347                                     'st', '-u')
1348  # Do a status -u at --depth immediates.
1349  expected_output = svntest.verify.UnorderedOutput(status[:4])
1350  svntest.actions.run_and_verify_svn(expected_output, [],
1351                                    'st', '-u', '--depth', 'immediates')
1352
1353#----------------------------------------------------------------------
1354
1355# Issue #3039.
1356@Issue(3039)
1357def depthy_update_above_dir_to_be_deleted(sbox):
1358  "'update -N' above a WC path deleted in repos HEAD"
1359  sbox.build()
1360
1361  sbox_for_depth = {
1362    "files" : sbox,
1363    "immediates" : sbox.clone_dependent(copy_wc=True),
1364    "empty" : sbox.clone_dependent(copy_wc=True),
1365    }
1366
1367  exit_code, output, err = svntest.actions.run_and_verify_svn(
1368    None, [],
1369    "delete", "-m", "Delete A.", sbox.repo_url + "/A")
1370
1371  def empty_output(wc_dir):
1372    return svntest.wc.State(wc_dir, { })
1373
1374  def output_with_A(wc_dir):
1375    expected_output = empty_output(wc_dir)
1376    expected_output.add({
1377      "A" : Item(status="D "),
1378      })
1379    return expected_output
1380
1381  initial_disk = svntest.main.greek_state.copy()
1382  disk_with_only_iota = svntest.wc.State("", {
1383    "iota" : Item("This is the file 'iota'.\n"),
1384    })
1385
1386  def status_with_dot(wc_dir):
1387    expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1388    expected_status.tweak("", wc_rev=2)
1389    return expected_status
1390
1391  def status_with_iota(wc_dir):
1392    expected_status = status_with_dot(wc_dir)
1393    expected_status.tweak("iota", wc_rev=2)
1394    return expected_status
1395
1396  def status_with_only_iota(wc_dir):
1397    return svntest.wc.State(wc_dir, {
1398      ""     : Item(status="  ", wc_rev=2),
1399      "iota" : Item(status="  ", wc_rev=2),
1400      })
1401
1402  expected_trees_for_depth = {
1403    "files"      : (empty_output, initial_disk, status_with_iota),
1404    "immediates" : (output_with_A, disk_with_only_iota, status_with_only_iota),
1405    "empty"      : (empty_output, initial_disk, status_with_dot),
1406    }
1407
1408  for depth in sbox_for_depth.keys():
1409    wc_dir = sbox_for_depth[depth].wc_dir
1410    (expected_output_func, expected_disk, expected_status_func) = \
1411      expected_trees_for_depth[depth]
1412    #print depth
1413    svntest.actions.run_and_verify_update(wc_dir,
1414                                          expected_output_func(wc_dir),
1415                                          expected_disk,
1416                                          expected_status_func(wc_dir),
1417                                          [], False,
1418                                          "--depth=%s" % depth, wc_dir)
1419
1420
1421#----------------------------------------------------------------------
1422
1423# Tests for deselection interface (a.k.a folding subtrees).
1424#----------------------------------------------------------------------
1425def depth_folding_clean_trees_1(sbox):
1426  "gradually fold wc from depth=infinity to empty"
1427
1428  # Covers the following situations:
1429  #
1430  #  infinity->immediates (metadata only)
1431  #  immediates->files (metadata only)
1432  #  mixed(infinity+files)=>immediates
1433  #  infinity=>empty
1434  #  immediates=>empty
1435  #  mixed(infinity+empty)=>immediates
1436  #  mixed(infinity+empty/immediates)=>immediates
1437  #  immediates=>files
1438  #  files=>empty
1439  #  mixed(infinity+empty)=>files
1440
1441  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
1442                                                             infinity=True)
1443
1444  A_path = sbox.ospath('A')
1445  C_path = os.path.join(A_path, 'C')
1446  B_path = os.path.join(A_path, 'B')
1447  D_path = os.path.join(A_path, 'D')
1448  E_path = os.path.join(B_path, 'E')
1449  F_path = os.path.join(B_path, 'F')
1450  G_path = os.path.join(D_path, 'G')
1451  H_path = os.path.join(D_path, 'H')
1452
1453  # Run 'svn up --set-depth=immediates' to directory A/B/E.
1454  # This is an infinity=>immediates folding, changes on metadata only
1455  expected_output = svntest.wc.State(wc_dir, {})
1456  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1457  expected_disk = svntest.main.greek_state.copy()
1458  svntest.actions.run_and_verify_update(wc_dir,
1459                                        expected_output,
1460                                        expected_disk,
1461                                        expected_status,
1462                                        [], False,
1463                                        '--set-depth', 'immediates', E_path)
1464  verify_depth(None, "immediates", E_path)
1465
1466  # Run 'svn up --set-depth=files' to directory A/B/E.
1467  # This is an immediates=>files folding, changes on metadata only
1468  svntest.actions.run_and_verify_update(wc_dir,
1469                                        expected_output,
1470                                        expected_disk,
1471                                        expected_status,
1472                                        [], False,
1473                                        '--set-depth', 'files', E_path)
1474  verify_depth(None, "files", E_path)
1475
1476  # Run 'svn up --set-depth=immediates' to directory A/B.
1477  # This is an mixed(infinity+files)=>immediates folding
1478  expected_output = svntest.wc.State(wc_dir, {
1479    'A/B/E/alpha'    : Item(status='D '),
1480    'A/B/E/beta'     : Item(status='D '),
1481    })
1482  expected_status.remove('A/B/E/alpha', 'A/B/E/beta')
1483  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta')
1484  svntest.actions.run_and_verify_update(wc_dir,
1485                                        expected_output,
1486                                        expected_disk,
1487                                        expected_status,
1488                                        [], False,
1489                                        '--set-depth', 'immediates', B_path)
1490  verify_depth(None, "immediates", B_path)
1491  verify_depth(None, "empty", E_path)
1492  verify_depth(None, "empty", F_path)
1493
1494  # Run 'svn up --set-depth=empty' to directory A/D/H
1495  # This is an infinity=>empty folding.
1496  expected_output = svntest.wc.State(wc_dir, {
1497    'A/D/H/chi'      : Item(status='D '),
1498    'A/D/H/psi'      : Item(status='D '),
1499    'A/D/H/omega'    : Item(status='D ')
1500    })
1501  expected_status.remove( 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
1502  expected_disk.remove( 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega')
1503  svntest.actions.run_and_verify_update(wc_dir,
1504                                        expected_output,
1505                                        expected_disk,
1506                                        expected_status,
1507                                        [], False,
1508                                        '--set-depth', 'empty', H_path)
1509  verify_depth(None, "empty", H_path)
1510
1511  # Run 'svn up --set-depth=immediates' to directory A/D
1512  # This is an mixed(infinity+empty)=>immediates folding.
1513  expected_output = svntest.wc.State(wc_dir, {
1514    'A/D/G/pi'       : Item(status='D '),
1515    'A/D/G/rho'      : Item(status='D '),
1516    'A/D/G/tau'      : Item(status='D '),
1517    })
1518  expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1519  expected_disk.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
1520  svntest.actions.run_and_verify_update(wc_dir,
1521                                        expected_output,
1522                                        expected_disk,
1523                                        expected_status,
1524                                        [], False,
1525                                        '--set-depth', 'immediates', D_path)
1526  verify_depth(None, "immediates", D_path)
1527  verify_depth(None, "empty", G_path)
1528
1529  # Run 'svn up --set-depth=empty' to directory A/D
1530  # This is an immediates=>empty folding.
1531  expected_output = svntest.wc.State(wc_dir, {
1532    'A/D/G'          : Item(status='D '),
1533    'A/D/H'          : Item(status='D '),
1534    'A/D/gamma'      : Item(status='D ')
1535    })
1536  expected_status.remove('A/D/gamma', 'A/D/G', 'A/D/H')
1537  expected_disk.remove('A/D/gamma', 'A/D/G', 'A/D/H')
1538  svntest.actions.run_and_verify_update(wc_dir,
1539                                        expected_output,
1540                                        expected_disk,
1541                                        expected_status,
1542                                        [], False,
1543                                        '--set-depth', 'empty', D_path)
1544  verify_depth(None, "empty", D_path)
1545
1546  # Run 'svn up --set-depth=immediates' to directory A
1547  # This is an mixed(infinity+empty/immediates)=>immediates folding.
1548  expected_output = svntest.wc.State(wc_dir, {
1549    'A/B/E'          : Item(status='D '),
1550    'A/B/F'          : Item(status='D '),
1551    'A/B/lambda'     : Item(status='D ')
1552    })
1553  expected_status.remove('A/B/lambda', 'A/B/E', 'A/B/F')
1554  expected_disk.remove('A/B/lambda', 'A/B/E', 'A/B/F')
1555  svntest.actions.run_and_verify_update(wc_dir,
1556                                        expected_output,
1557                                        expected_disk,
1558                                        expected_status,
1559                                        [], False,
1560                                        '--set-depth', 'immediates', A_path)
1561  verify_depth(None, "immediates", A_path)
1562  verify_depth(None, "empty", C_path)
1563  verify_depth(None, "empty", B_path)
1564
1565  # Run 'svn up --set-depth=files' to directory A
1566  # This is an immediates=>files folding.
1567  expected_output = svntest.wc.State(wc_dir, {
1568    'A/B'            : Item(status='D '),
1569    'A/C'            : Item(status='D '),
1570    'A/D'            : Item(status='D ')
1571    })
1572  expected_status.remove('A/B', 'A/C', 'A/D')
1573  expected_disk.remove('A/B', 'A/C', 'A/D')
1574  svntest.actions.run_and_verify_update(wc_dir,
1575                                        expected_output,
1576                                        expected_disk,
1577                                        expected_status,
1578                                        [], False,
1579                                        '--set-depth', 'files', A_path)
1580  verify_depth(None, "files", A_path)
1581
1582  # Run 'svn up --set-depth=empty' to directory A
1583  # This is an files=>empty folding.
1584  expected_output = svntest.wc.State(wc_dir, {
1585    'A/mu'            : Item(status='D ')
1586    })
1587  expected_status.remove('A/mu')
1588  expected_disk.remove('A/mu')
1589  svntest.actions.run_and_verify_update(wc_dir,
1590                                        expected_output,
1591                                        expected_disk,
1592                                        expected_status,
1593                                        [], False,
1594                                        '--set-depth', 'empty', A_path)
1595  verify_depth(None, "empty", A_path)
1596
1597  # Run 'svn up --set-depth=files' to wc
1598  # This is an mixed(infinity+empty)=>files folding.
1599  expected_output = svntest.wc.State(wc_dir, {
1600    'A'            : Item(status='D ')
1601    })
1602  expected_status.remove('A')
1603  expected_disk.remove('A')
1604  svntest.actions.run_and_verify_update(wc_dir,
1605                                        expected_output,
1606                                        expected_disk,
1607                                        expected_status,
1608                                        [], False,
1609                                        '--set-depth', 'files', wc_dir)
1610  verify_depth(None, "files", wc_dir)
1611
1612
1613#------------------------------------------------------------------------------
1614def depth_folding_clean_trees_2(sbox):
1615  "gradually fold wc, focusing on depth=immediates"
1616
1617  # Covers the following situations:
1618  #
1619  #  infinity=>immediates
1620  #  mixed(immediates+immediates)=>immediates
1621  #  mixed(immediates+infinity)=>immediates
1622  #  mixed(immediates+files)=>immediates
1623  #  immediates=>empty(remove the target since the parent is at files/empty)
1624
1625  ign_a, wc_dir, ign_b, ign_c = set_up_depthy_working_copies(sbox, files=True)
1626
1627  A_path = os.path.join(wc_dir, 'A')
1628  D_path = os.path.join(A_path, 'D')
1629  H_path = os.path.join(D_path, 'H')
1630  G_path = os.path.join(D_path, 'G')
1631
1632  # pull in directory A at immediates
1633  svntest.actions.run_and_verify_svn(None, [],
1634                                     'up', '--depth', 'immediates', A_path)
1635  # check to see if it's really at immediates
1636  verify_depth(None, "immediates", A_path)
1637
1638  # pull in directory D at infinity
1639  svntest.actions.run_and_verify_svn(None, [],
1640                                     'up', '--set-depth', 'infinity', D_path)
1641
1642  # Run 'svn up --set-depth=immediates' to directory A/D.
1643  # This is an infinity=>immediates folding
1644  expected_output = svntest.wc.State(wc_dir, {
1645    'A/D/G/pi'       : Item(status='D '),
1646    'A/D/G/rho'      : Item(status='D '),
1647    'A/D/G/tau'      : Item(status='D '),
1648    'A/D/H/chi'      : Item(status='D '),
1649    'A/D/H/psi'      : Item(status='D '),
1650    'A/D/H/omega'    : Item(status='D ')
1651    })
1652  expected_status = svntest.wc.State(wc_dir, {
1653    ''               : Item(status='  ', wc_rev=1),
1654    'iota'           : Item(status='  ', wc_rev=1),
1655    'A'              : Item(status='  ', wc_rev=1),
1656    'A/mu'           : Item(status='  ', wc_rev=1),
1657    'A/B'            : Item(status='  ', wc_rev=1),
1658    'A/C'            : Item(status='  ', wc_rev=1),
1659    'A/D'            : Item(status='  ', wc_rev=1),
1660    'A/D/gamma'      : Item(status='  ', wc_rev=1),
1661    'A/D/G'          : Item(status='  ', wc_rev=1),
1662    'A/D/H'          : Item(status='  ', wc_rev=1)
1663    })
1664  expected_disk = svntest.wc.State('', {
1665    'iota'        : Item(contents="This is the file 'iota'.\n"),
1666    'A'           : Item(contents=None),
1667    'A/mu'        : Item(contents="This is the file 'mu'.\n"),
1668    'A/B'         : Item(contents=None),
1669    'A/C'         : Item(contents=None),
1670    'A/D'         : Item(contents=None),
1671    'A/D/gamma'   : Item(contents="This is the file 'gamma'.\n"),
1672    'A/D/G'       : Item(contents=None),
1673    'A/D/H'       : Item(contents=None),
1674    })
1675  svntest.actions.run_and_verify_update(wc_dir,
1676                                        expected_output,
1677                                        expected_disk,
1678                                        expected_status,
1679                                        [], False,
1680                                        '--set-depth', 'immediates', D_path)
1681  verify_depth(None, "immediates", D_path)
1682  verify_depth(None, "empty", G_path)
1683  verify_depth(None, "empty", H_path)
1684
1685  # Run 'svn up --set-depth=immediates' to directory A.
1686  # This is an mixed(immediates+immediates)=>immediates folding
1687  expected_output = svntest.wc.State(wc_dir, {
1688    'A/D/G'      : Item(status='D '),
1689    'A/D/H'      : Item(status='D '),
1690    'A/D/gamma'  : Item(status='D ')
1691    })
1692  expected_status.remove( 'A/D/G', 'A/D/H', 'A/D/gamma')
1693  expected_disk.remove( 'A/D/G', 'A/D/H', 'A/D/gamma')
1694  svntest.actions.run_and_verify_update(wc_dir,
1695                                        expected_output,
1696                                        expected_disk,
1697                                        expected_status,
1698                                        [], False,
1699                                        '--set-depth', 'immediates', A_path)
1700  verify_depth(None, "immediates", A_path)
1701  verify_depth(None, "empty", D_path)
1702
1703  # pull in directory D at infinity
1704  svntest.actions.run_and_verify_svn(None, [],
1705                                     'up', '--set-depth', 'infinity', D_path)
1706
1707  # Run 'svn up --set-depth=immediates' to directory A.
1708  # This is an mixed(immediates+infinity)=>immediates folding
1709  expected_output = svntest.wc.State(wc_dir, {
1710    'A/D/gamma'      : Item(status='D '),
1711    'A/D/G'          : Item(status='D '),
1712    'A/D/H'          : Item(status='D '),
1713    })
1714  svntest.actions.run_and_verify_update(wc_dir,
1715                                        expected_output,
1716                                        expected_disk,
1717                                        expected_status,
1718                                        [], False,
1719                                        '--set-depth', 'immediates', A_path)
1720  verify_depth(None, "immediates", A_path)
1721  verify_depth(None, "empty", D_path)
1722
1723  # pull in directory D at files
1724  svntest.actions.run_and_verify_svn(None, [],
1725                                     'up', '--set-depth', 'files', D_path)
1726
1727  # Run 'svn up --set-depth=immediates' to directory A.
1728  # This is an mixed(immediates+files)=>immediates folding
1729  expected_output = svntest.wc.State(wc_dir, {
1730    'A/D/gamma'      : Item(status='D ')
1731    })
1732  svntest.actions.run_and_verify_update(wc_dir,
1733                                        expected_output,
1734                                        expected_disk,
1735                                        expected_status,
1736                                        [], False,
1737                                        '--set-depth', 'immediates', A_path)
1738  verify_depth(None, "immediates", A_path)
1739  verify_depth(None, "empty", D_path)
1740
1741#  Comment the following out, since cropping out the root of tree is now
1742#  handled by svn_depth_exclude and should have a separate test case for all
1743#  influenced commands.
1744#
1745#  # Run 'svn up --set-depth=empty' to directory A.
1746#  # This is an immediates=>empty folding, the directory A should be deleted
1747#  # too since the parent directory is at files/empty
1748#  expected_output = svntest.wc.State(wc_dir, {
1749#    'A'              : Item(status='D '),
1750#    })
1751#  expected_status = svntest.wc.State(wc_dir, {
1752#    ''               : Item(status='  ', wc_rev=1),
1753#    'iota'           : Item(status='  ', wc_rev=1)
1754#    })
1755#  expected_disk = svntest.wc.State('', {
1756#    'iota'        : Item(contents="This is the file 'iota'.\n")
1757#    })
1758#  svntest.actions.run_and_verify_update(wc_dir,
1759#                                        expected_output,
1760#                                        expected_disk,
1761#                                        expected_status,
1762#                                        [], False,
1763#                                        '--set-depth', 'empty', A_path)
1764
1765def depth_fold_expand_clean_trees(sbox):
1766  "expand target while contracting subtree"
1767  #  --set-depth=immediates/files to an empty target with infinity
1768  #  sub-tree should both fold the subtree and expand the target
1769
1770  wc_dir, ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox, empty=True)
1771
1772  A_path = os.path.join(wc_dir, 'A')
1773  B_path = os.path.join(A_path, 'B')
1774  C_path = os.path.join(A_path, 'C')
1775  D_path = os.path.join(A_path, 'D')
1776
1777  # pull in directory A at empty
1778  svntest.actions.run_and_verify_svn(None, [],
1779                                     'up', '--depth', 'empty', A_path)
1780  verify_depth(None, "empty", A_path)
1781
1782  # pull in directory D at infinity
1783  svntest.actions.run_and_verify_svn(None, [],
1784                                     'up', D_path)
1785
1786  # Make the other working copy.
1787  other_wc = sbox.add_wc_path('other')
1788  svntest.actions.duplicate_dir(wc_dir, other_wc)
1789
1790  # Run 'svn up --set-depth=immediates' to directory A. This both folds
1791  # directory D to empty and expands directory A to immediates
1792  expected_output = svntest.wc.State(wc_dir, {
1793    'A/mu'           : Item(status='A '),
1794    'A/B'            : Item(status='A '),
1795    'A/C'            : Item(status='A '),
1796    'A/D/gamma'      : Item(status='D '),
1797    'A/D/G'          : Item(status='D '),
1798    'A/D/H'          : Item(status='D '),
1799    })
1800  expected_status = svntest.wc.State(wc_dir, {
1801    ''               : Item(status='  ', wc_rev=1),
1802    'A'              : Item(status='  ', wc_rev=1),
1803    'A/mu'           : Item(status='  ', wc_rev=1),
1804    'A/B'            : Item(status='  ', wc_rev=1),
1805    'A/C'            : Item(status='  ', wc_rev=1),
1806    'A/D'            : Item(status='  ', wc_rev=1)
1807    })
1808  expected_disk = svntest.wc.State('', {
1809    'A'           : Item(contents=None),
1810    'A/mu'        : Item(contents="This is the file 'mu'.\n"),
1811    'A/B'         : Item(contents=None),
1812    'A/C'         : Item(contents=None),
1813    'A/D'         : Item(contents=None)
1814    })
1815  svntest.actions.run_and_verify_update(wc_dir,
1816                                        expected_output,
1817                                        expected_disk,
1818                                        expected_status,
1819                                        [], False,
1820                                        '--set-depth', 'immediates', A_path)
1821  verify_depth(None, "immediates", A_path)
1822  verify_depth(None, "empty", B_path)
1823  verify_depth(None, "empty", C_path)
1824  verify_depth(None, "empty", D_path)
1825
1826  # Run 'svn up --set-depth=files' to directory A in other_wc. This both
1827  # removes directory D and expands directory A to files
1828  expected_output = svntest.wc.State(other_wc, {
1829    'A/mu'           : Item(status='A '),
1830    'A/D'            : Item(status='D '),
1831    })
1832  expected_status = svntest.wc.State(other_wc, {
1833    ''               : Item(status='  ', wc_rev=1),
1834    'A'              : Item(status='  ', wc_rev=1),
1835    'A/mu'           : Item(status='  ', wc_rev=1),
1836    })
1837  expected_disk = svntest.wc.State('', {
1838    'A'           : Item(contents=None),
1839    'A/mu'        : Item(contents="This is the file 'mu'.\n")
1840    })
1841  Other_A_path = os.path.join(other_wc, 'A')
1842  svntest.actions.run_and_verify_update(other_wc,
1843                                        expected_output,
1844                                        expected_disk,
1845                                        expected_status,
1846                                        [], False,
1847                                        '--set-depth', 'files', Other_A_path)
1848  verify_depth(None, "files", Other_A_path)
1849
1850
1851def pull_in_tree_with_depth_option(sbox):
1852  """checkout and verify subtree with depth immediates"""
1853
1854  wc_empty,ign_a, ign_b, ign_c = set_up_depthy_working_copies(sbox,
1855                                                              empty=True)
1856  A_path = os.path.join(wc_empty, 'A')
1857  expected_output = svntest.wc.State(wc_empty, {
1858    'A'      : Item(status='A '),
1859    'A/mu'   : Item(status='A '),
1860    'A/B'    : Item(status='A '),
1861    'A/C'    : Item(status='A '),
1862    'A/D'    : Item(status='A ')
1863    })
1864  expected_disk = svntest.wc.State('', {
1865    'A'      : Item(),
1866    'A/mu'   : Item("This is the file 'mu'.\n"),
1867    'A/B'    : Item(),
1868    'A/C'    : Item(),
1869    'A/D'    : Item(),
1870    })
1871  expected_status = svntest.wc.State(wc_empty, {
1872    ''       : Item(status='  ', wc_rev=1),
1873    'A'      : Item(status='  ', wc_rev=1),
1874    'A/mu'   : Item(status='  ', wc_rev=1),
1875    'A/B'    : Item(status='  ', wc_rev=1),
1876    'A/C'    : Item(status='  ', wc_rev=1),
1877    'A/D'    : Item(status='  ', wc_rev=1),
1878    })
1879  svntest.actions.run_and_verify_update(wc_empty,
1880                                        expected_output,
1881                                        expected_disk,
1882                                        expected_status,
1883                                        [], False,
1884                                        "--depth=immediates", A_path)
1885
1886  # Check that the A directory was pull ed in at depth=immediates.
1887  verify_depth(None, "immediates", A_path)
1888
1889def fold_tree_with_unversioned_modified_items(sbox):
1890  "unversioned & modified items left untouched"
1891  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
1892                                                             infinity=True)
1893
1894  A_path = sbox.ospath('A')
1895  pi_path = os.path.join(A_path, 'D', 'G', 'pi')
1896  mu_path = os.path.join(A_path, 'mu')
1897  unv_path = os.path.join(A_path, 'B', 'unv')
1898
1899  # Modify file pi
1900  svntest.main.file_write(pi_path, "pi modified\n")
1901  # Modify file mu
1902  svntest.main.file_write(mu_path, "mu modified\n")
1903  # Create an unversioned file
1904  svntest.main.file_write(unv_path, "new unversioned\n")
1905
1906  # Fold the A dir to empty, expect the modified & unversioned ones left
1907  # unversioned rather than removed, along with paths to those items.
1908
1909  # Directories B and D won't be deleted, because that would remove their
1910  # local modifications. Their unmodified descendants are deleted though.
1911  expected_output = svntest.wc.State(wc_dir, {
1912    'A/B/E'          : Item(status='D '),
1913    'A/B/F'          : Item(status='D '),
1914    'A/B/lambda'     : Item(status='D '),
1915    'A/C'            : Item(status='D '),
1916    'A/D/G/rho'      : Item(status='D '),
1917    'A/D/G/tau'      : Item(status='D '),
1918    'A/D/H'          : Item(status='D '),
1919    'A/D/gamma'      : Item(status='D '),
1920    })
1921  # unversioned items will be ignored in in the status tree, since the
1922  # run_and_verify_update() function uses a quiet version of svn status
1923  expected_status = svntest.wc.State(wc_dir, {
1924    ''               : Item(status='  ', wc_rev=1),
1925    'iota'           : Item(status='  ', wc_rev=1),
1926    'A'              : Item(status='  ', wc_rev=1),
1927    'A/D'            : Item(status='  ', wc_rev='1'),
1928    'A/D/G'          : Item(status='  ', wc_rev='1'),
1929    'A/D/G/pi'       : Item(status='M ', wc_rev='1'),
1930    'A/B'            : Item(status='  ', wc_rev='1'),
1931    'A/mu'           : Item(status='M ', wc_rev='1'),
1932    })
1933  expected_disk = svntest.wc.State('', {
1934    'iota'           : Item(contents="This is the file 'iota'.\n"),
1935    'A'              : Item(contents=None),
1936    'A/mu'           : Item(contents="mu modified\n"),
1937    'A/B'            : Item(contents=None),
1938    'A/B/unv'        : Item(contents="new unversioned\n"),
1939    'A/D'            : Item(contents=None),
1940    'A/D/G'          : Item(contents=None),
1941    'A/D/G/pi'       : Item(contents="pi modified\n")
1942    })
1943  svntest.actions.run_and_verify_update(wc_dir,
1944                                        expected_output,
1945                                        expected_disk,
1946                                        expected_status,
1947                                        [], False,
1948                                        '--set-depth', 'empty', A_path)
1949  verify_depth(None, "empty", A_path)
1950
1951def depth_empty_update_on_file(sbox):
1952  "depth-empty update on a file doesn't break it"
1953  sbox.build()
1954  wc_dir = sbox.wc_dir
1955
1956  iota_path = sbox.ospath('iota')
1957
1958  # Change iota and commit it in r2.
1959  svntest.main.file_write(iota_path, 'Modified iota\n')
1960  expected_output = svntest.wc.State(wc_dir, { 'iota' : Item(verb='Sending'), })
1961  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1962  expected_status.tweak('iota', wc_rev=2, status='  ')
1963  svntest.actions.run_and_verify_commit(wc_dir,
1964                                        expected_output,
1965                                        expected_status)
1966
1967  # Update iota with depth=empty.
1968  expected_output = svntest.wc.State(wc_dir,
1969                                     {'iota': Item(status='U ') })
1970  expected_disk = svntest.main.greek_state.copy()
1971  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1972  svntest.actions.run_and_verify_update(wc_dir,
1973                                        expected_output,
1974                                        expected_disk,
1975                                        expected_status,
1976                                        [], False,
1977                                        '--depth=empty', '-r1', iota_path)
1978
1979  # Check the revision and created rev.
1980  expected_infos = {
1981      'Revision'           : '^1$',
1982      'Last Changed Rev'   : '^1$',
1983    }
1984  svntest.actions.run_and_verify_info([expected_infos], iota_path)
1985
1986
1987@Issue(3544)
1988def excluded_path_update_operation(sbox):
1989  """make sure update handle svn_depth_exclude properly"""
1990
1991  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
1992                                                             infinity=True)
1993  A_path = sbox.ospath('A')
1994  B_path = os.path.join(A_path, 'B')
1995  L_path = os.path.join(A_path, 'L')
1996  E_path = os.path.join(B_path, 'E')
1997  iota_path = sbox.ospath('iota')
1998
1999  # Simply exclude a subtree
2000  expected_output = svntest.wc.State(wc_dir, {
2001    'A/B/E'            : Item(status='D '),
2002    })
2003  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2004  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
2005  expected_disk = svntest.main.greek_state.copy()
2006  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
2007
2008  svntest.actions.run_and_verify_update(wc_dir,
2009                                        expected_output,
2010                                        expected_disk,
2011                                        expected_status,
2012                                        [], False,
2013                                        '--set-depth', 'exclude', E_path)
2014  # verify_depth exclude? not implemented yet
2015
2016  # crop path B to immediates, this just pull in A/B/E again
2017  expected_output = svntest.wc.State(wc_dir, {
2018    'A/B/E'            : Item(status='A '),
2019    })
2020  expected_status.add({
2021    'A/B/E'            : Item(status='  ', wc_rev=1)
2022    })
2023  expected_disk.add({
2024    'A/B/E'          : Item(contents=None),
2025    })
2026  svntest.actions.run_and_verify_update(wc_dir,
2027                                        expected_output,
2028                                        expected_disk,
2029                                        expected_status,
2030                                        [], False,
2031                                        '--set-depth', 'immediates', B_path)
2032  verify_depth(None, "immediates", B_path)
2033
2034  # Exclude A/B/E again
2035  svntest.actions.run_and_verify_svn(None, [],
2036                                     'up', '--set-depth', 'exclude', E_path)
2037
2038  # Exclude path B totally, in which contains an excluded subtree.
2039  expected_output = svntest.wc.State(wc_dir, {
2040    'A/B'            : Item(status='D '),
2041    })
2042  expected_status.remove('A/B/F', 'A/B/E', 'A/B/lambda', 'A/B')
2043  expected_disk.remove('A/B/F', 'A/B/E', 'A/B/lambda', 'A/B')
2044  svntest.actions.run_and_verify_update(wc_dir,
2045                                        expected_output,
2046                                        expected_disk,
2047                                        expected_status,
2048                                        [], False,
2049                                        '--set-depth', 'exclude', B_path)
2050
2051  # Explicitly pull in excluded path B.
2052  expected_output = svntest.wc.State(wc_dir, {
2053    'A/B'            : Item(status='A '),
2054    'A/B/lambda'     : Item(status='A '),
2055    'A/B/E'          : Item(status='A '),
2056    'A/B/E/alpha'    : Item(status='A '),
2057    'A/B/E/beta'     : Item(status='A '),
2058    'A/B/F'          : Item(status='A '),
2059    })
2060  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2061  expected_disk = svntest.main.greek_state.copy()
2062  svntest.actions.run_and_verify_update(wc_dir,
2063                                        expected_output,
2064                                        expected_disk,
2065                                        expected_status,
2066                                        [], False,
2067                                        B_path)
2068
2069  # Test issue #
2070  # Exclude a file then set depth of WC to infinity, the file should return.
2071  expected_output = svntest.wc.State(wc_dir, {
2072    'iota' : Item(status='D '),
2073    })
2074  expected_status.remove('iota')
2075  expected_disk.remove('iota')
2076  svntest.actions.run_and_verify_update(wc_dir,
2077                                        expected_output,
2078                                        expected_disk,
2079                                        expected_status,
2080                                        [], False,
2081                                        '--set-depth', 'exclude', iota_path)
2082
2083  # Update the whole WC to depth=infinity.
2084  expected_output = svntest.wc.State(wc_dir, {
2085    'iota' : Item(status='A '),
2086    })
2087  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2088  expected_disk = svntest.main.greek_state.copy()
2089  # This update currently fails when iota is reported as added, but shows in
2090  # status as unversioned.  See issue #3544 'svn update does not restore
2091  # excluded files'.  This test is marked as XFail until that issue is fixed.
2092  svntest.actions.run_and_verify_update(wc_dir,
2093                                        expected_output,
2094                                        expected_disk,
2095                                        expected_status,
2096                                        [], False,
2097                                        '--set-depth', 'infinity', wc_dir)
2098
2099def excluded_path_misc_operation(sbox):
2100  """make sure other subcommands handle exclude"""
2101
2102  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
2103                                                             infinity=True)
2104  A_path = sbox.ospath('A')
2105  B_path = os.path.join(A_path, 'B')
2106  L_path = os.path.join(A_path, 'L')
2107  M_path = os.path.join(A_path, 'M')
2108  E_path = os.path.join(B_path, 'E')
2109  LE_path = os.path.join(L_path, 'E')
2110
2111  # Simply exclude a subtree
2112  expected_output = svntest.wc.State(wc_dir, {
2113    'A/B/E'            : Item(status='D '),
2114    })
2115  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2116  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
2117  expected_disk = svntest.main.greek_state.copy()
2118  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
2119
2120  svntest.actions.run_and_verify_update(wc_dir,
2121                                        expected_output,
2122                                        expected_disk,
2123                                        expected_status,
2124                                        [], False,
2125                                        '--set-depth', 'exclude', E_path)
2126
2127  # copy A/B to A/L, excluded entry should be copied too
2128  expected_output = ['A         '+L_path+'\n']
2129  svntest.actions.run_and_verify_svn(expected_output, [],
2130                                     'cp', B_path, L_path)
2131  # verify_depth exclude? not implemented yet
2132  #verify_depth(None, "empty", LE_path)
2133
2134  # revert A/L, with an excluded item in the tree
2135  revert_paths = [L_path] + [os.path.join(L_path, child)
2136                             for child in ['E', 'F', 'lambda']]
2137  expected_output = svntest.verify.UnorderedOutput([
2138    "Reverted '%s'\n" % path for path in revert_paths])
2139
2140  svntest.actions.run_and_verify_svn(expected_output, [],
2141                                     'revert', '--depth=infinity', L_path)
2142
2143  # copy A/B to A/L and then cp A/L to A/M, excluded entry should be
2144  # copied both times
2145  expected_output = ['A         '+L_path+'\n']
2146  svntest.actions.run_and_verify_svn(expected_output, [],
2147                                     'cp', B_path, L_path)
2148  expected_output = ['A         '+M_path+'\n']
2149  svntest.actions.run_and_verify_svn(expected_output, [],
2150                                     'cp', L_path, M_path)
2151
2152  # commit this copy, with an excluded item.
2153  expected_output = svntest.wc.State(wc_dir, { 'A/L' : Item(verb='Adding'),
2154                                               'A/M' : Item(verb='Adding'), })
2155  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2156  expected_status.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
2157  expected_status.add({
2158    'A/L'        : Item(status='  ', wc_rev=2),
2159    'A/L/lambda' : Item(status='  ', wc_rev=2),
2160    'A/L/F'      : Item(status='  ', wc_rev=2),
2161    'A/M'        : Item(status='  ', wc_rev=2),
2162    'A/M/lambda' : Item(status='  ', wc_rev=2),
2163    'A/M/F'      : Item(status='  ', wc_rev=2),
2164    })
2165  svntest.actions.run_and_verify_commit(wc_dir,
2166                                        expected_output,
2167                                        expected_status)
2168
2169  # Relocate wc, with excluded items in it.
2170  repo_dir = sbox.repo_dir
2171  repo_url = sbox.repo_url
2172  other_repo_dir, other_repo_url = sbox.add_repo_path('other')
2173  svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 0)
2174  svntest.main.safe_rmtree(repo_dir, 1)
2175  svntest.actions.run_and_verify_svn(None, [], 'switch', '--relocate',
2176                                     repo_url, other_repo_url, wc_dir)
2177
2178  # remove the new directory A/L, with an excluded item.
2179  # If successed, no error will be thrown
2180  svntest.actions.run_and_verify_svn(None, [],
2181                                     'rm', L_path)
2182
2183  # revert the delete
2184  # If successed, no error will be thrown
2185  svntest.actions.run_and_verify_svn(None, [],
2186                                     'revert', '--depth=infinity', L_path)
2187
2188
2189def excluded_receive_remote_removal(sbox):
2190  """exclude flag should be cleared upon remote removal"""
2191  ign_a, ign_b, ign_c, wc \
2192         = set_up_depthy_working_copies(sbox, infinity=True)
2193
2194  A_path = os.path.join(wc, 'A')
2195  B_path = os.path.join(A_path, 'B')
2196  C_path = os.path.join(A_path, 'C')
2197
2198  # Exclude path B from wc
2199  expected_output = svntest.wc.State(wc, {
2200    'A/B'            : Item(status='D '),
2201    })
2202  expected_disk = svntest.main.greek_state.copy()
2203  expected_disk.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2204                       'A/B/E', 'A/B/F', 'A/B')
2205  expected_status = svntest.actions.get_virginal_state(wc, 1)
2206  expected_status.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2207                         'A/B/E', 'A/B/F', 'A/B')
2208  svntest.actions.run_and_verify_update(wc,
2209                                        expected_output,
2210                                        expected_disk,
2211                                        expected_status,
2212                                        [], False,
2213                                        "--set-depth", "exclude", B_path)
2214
2215  # Remove path B in the repos.
2216  svntest.actions.run_and_verify_svn(None, [], "delete", "-m",
2217                                     "Delete B.", sbox.repo_url + "/A/B")
2218
2219  # Update wc, should receive the removal of excluded path B
2220  # and handle it silently.
2221  expected_status = svntest.actions.get_virginal_state(wc, 2)
2222  expected_status.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2223                         'A/B/E', 'A/B/F', 'A/B')
2224  svntest.actions.run_and_verify_update(wc,
2225                                        None,
2226                                        expected_disk,
2227                                        expected_status)
2228
2229  # Introduce a new path with the same name B.
2230  # This should succeed if the exclude entry is gone with the update,
2231  # otherwise a name conflict will rise up.
2232  expected_output = ['A         '+B_path+'\n']
2233  svntest.actions.run_and_verify_svn(expected_output, [],
2234                                     'cp', C_path, B_path)
2235
2236
2237# Regression test for r876760.
2238def exclude_keeps_hidden_entries(sbox):
2239  "'up --set-depth exclude' doesn't lose entries"
2240
2241  sbox.build()
2242  wc_dir = sbox.wc_dir
2243
2244  A_path = sbox.ospath('A')
2245  os.chdir(A_path)
2246
2247  # the second 'up' used to cause the entry of 'C' to be lost.
2248  svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', 'C')
2249  svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', 'D')
2250  # we could grep the 'entries' file, but...
2251  # or we could use 'info', but info_excluded() is XFail.
2252  expected_stderr = ".*svn: E150002: '.*C' is already under version control.*"
2253  svntest.actions.run_and_verify_svn(None, expected_stderr,
2254                                     'mkdir', 'C')
2255
2256
2257@Issue(3792)
2258def info_excluded(sbox):
2259  "'info' should treat excluded item as versioned"
2260
2261  # The problem: 'svn info' on an excluded item would behave as if it
2262  # was not versioned at all:
2263  #
2264  #     % svn up --set-depth exclude A
2265  #     D         A
2266  #     % svn info A
2267  #     A:  (Not a versioned resource)
2268  #
2269  #     ..\..\..\subversion\svn\info-cmd.c:562: (apr_err=200000)
2270  #     svn: A problem occurred; see other errors for details
2271  #
2272  # It should acknowledge the existence (in the repos) of ./A and print some
2273  # info about it, like it does if '--set-depth empty' is used instead.
2274
2275  sbox.build()
2276  wc_dir = sbox.wc_dir
2277
2278  A_path = sbox.ospath('A')
2279  svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', A_path)
2280
2281  expected_info = {
2282      'Path' : re.escape(A_path),
2283      'Repository Root' : sbox.repo_url,
2284      'Repository UUID' : svntest.actions.get_wc_uuid(wc_dir),
2285      'Depth' : 'exclude',
2286  }
2287  svntest.actions.run_and_verify_info([expected_info], A_path)
2288
2289
2290
2291#----------------------------------------------------------------------
2292# Check that "svn resolved" visits tree-conflicts *on unversioned items*
2293# according to the --depth parameter.
2294
2295def make_depth_tree_conflicts(sbox):
2296  "Helper for tree_conflicts_resolved_depth_*"
2297
2298  sbox.build()
2299  wc = sbox.wc_dir
2300
2301  j = os.path.join
2302  A = j(wc, 'A')
2303  m =    j(A, 'mu')
2304  B =    j(A, 'B')
2305  D =    j(A, 'D')
2306  g =      j(D, 'gamma')
2307
2308  # Store node modifications as rev 2
2309  svntest.actions.run_and_verify_svn(None, [],
2310                                     'propset', 'foo', 'foo-val', B)
2311  svntest.main.file_append(m, "Modified mu.\n")
2312  svntest.main.file_append(g, "Modified gamma.\n")
2313
2314  expected_output = svntest.wc.State(wc, {
2315      'A/mu'              : Item(verb='Sending'),
2316      'A/B'               : Item(verb='Sending'),
2317      'A/D/gamma'         : Item(verb='Sending'),
2318    })
2319
2320  expected_status = svntest.actions.get_virginal_state(wc, 1)
2321  expected_status.tweak('A/mu', 'A/B', 'A/D/gamma',
2322                        wc_rev = 2)
2323
2324  svntest.actions.run_and_verify_commit(wc,
2325                                        expected_output,
2326                                        expected_status,
2327                                        [],
2328                                        A)
2329
2330  # Go back to rev 1
2331  expected_output = svntest.wc.State(wc, {
2332    'A/mu'              : Item(status='U '),
2333    'A/B'               : Item(status=' U'),
2334    'A/D/gamma'         : Item(status='U '),
2335  })
2336  expected_status = svntest.actions.get_virginal_state(wc, 1)
2337  expected_disk = svntest.main.greek_state.copy()
2338  svntest.actions.run_and_verify_update(wc,
2339                                        expected_output,
2340                                        expected_disk,
2341                                        expected_status,
2342                                        [], False,
2343                                        '-r1', A)
2344
2345  # Perform node deletions so that items become unversioned and
2346  # will have tree-conflicts upon update.
2347  svntest.actions.run_and_verify_svn(None, [],
2348                                     'rm', m, B, g)
2349
2350  # Update so that conflicts appear
2351  expected_output = svntest.wc.State(wc, {
2352    'A/mu'              : Item(status='  ', treeconflict='C'),
2353    'A/B'               : Item(status='  ', treeconflict='C'),
2354    'A/D/gamma'         : Item(status='  ', treeconflict='C'),
2355  })
2356
2357  expected_disk = svntest.main.greek_state.copy()
2358  expected_disk.remove('A/mu',
2359                       'A/B', 'A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta',
2360                       'A/D/gamma',
2361                       'A/B/E', 'A/B/F')
2362
2363  # This test is set XFail because this (correct) status cannot be
2364  # verified due to an "svn update" bug. The tree-conflict on A/B
2365  # which is notified about during the update does not show in the
2366  # status. When removing file 'mu' from above 'rm' command, 'B' is
2367  # reported as tree-conflicted correctly. Also use these to verify:
2368  #  expected_output = None
2369  #  expected_disk = None
2370  expected_status = svntest.actions.get_virginal_state(wc, 2)
2371  expected_status.tweak('A/mu',
2372                        'A/B', 'A/B/lambda',
2373                        'A/B/E', 'A/B/E/alpha', 'A/B/E/beta',
2374                        'A/B/F',
2375                        'A/D/gamma',
2376                        status='D ')
2377  expected_status.tweak('A/mu', 'A/B', 'A/D/gamma',
2378                        treeconflict='C')
2379
2380  svntest.actions.run_and_verify_update(wc,
2381                                        expected_output,
2382                                        expected_disk,
2383                                        expected_status,
2384                                        [], False,
2385                                        wc)
2386
2387
2388
2389def tree_conflicts_resolved_depth_empty(sbox):
2390  "tree conflicts resolved depth-empty"
2391
2392  make_depth_tree_conflicts(sbox)
2393
2394  wc = sbox.wc_dir
2395  A = os.path.join(wc, 'A')
2396
2397  svntest.actions.run_and_verify_resolved([], '--depth=empty', A)
2398
2399
2400def tree_conflicts_resolved_depth_files(sbox):
2401  "tree conflicts resolved depth-files"
2402
2403  make_depth_tree_conflicts(sbox)
2404
2405  wc = sbox.wc_dir
2406  j = os.path.join
2407  A = j(wc, 'A')
2408  m =    j(A, 'mu')
2409
2410  svntest.actions.run_and_verify_resolved([m], '--depth=files', A)
2411
2412
2413def tree_conflicts_resolved_depth_immediates(sbox):
2414  "tree conflicts resolved depth-immediates"
2415
2416  make_depth_tree_conflicts(sbox)
2417
2418  wc = sbox.wc_dir
2419  j = os.path.join
2420  A = j(wc, 'A')
2421  m =    j(A, 'mu')
2422  B =    j(A, 'B')
2423
2424  svntest.actions.run_and_verify_resolved([m, B], '--depth=immediates', A)
2425
2426
2427def tree_conflicts_resolved_depth_infinity(sbox):
2428  "tree conflicts resolved depth-infinity"
2429
2430  make_depth_tree_conflicts(sbox)
2431
2432  wc = sbox.wc_dir
2433  j = os.path.join
2434  A = j(wc, 'A')
2435  m =    j(A, 'mu')
2436  B =    j(A, 'B')
2437  g =    j(A, 'D', 'gamma')
2438
2439  svntest.actions.run_and_verify_resolved([m, B, g], '--depth=infinity', A)
2440
2441def update_excluded_path_sticky_depths(sbox):
2442  """set-depth from excluded to all other depths"""
2443
2444  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
2445                                                             infinity=True)
2446  A_path = sbox.ospath('A')
2447  B_path = os.path.join(A_path, 'B')
2448
2449  # Exclude the subtree 'A/B'
2450  expected_output = svntest.wc.State(wc_dir, {
2451    'A/B'            : Item(status='D '),
2452    })
2453  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2454  expected_status.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/E',
2455                         'A/B/F', 'A/B')
2456  expected_disk = svntest.main.greek_state.copy()
2457  expected_disk.remove('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/E',
2458                       'A/B/F', 'A/B')
2459
2460  svntest.actions.run_and_verify_update(wc_dir,
2461                                        expected_output,
2462                                        expected_disk,
2463                                        expected_status,
2464                                        [], False,
2465                                        '--set-depth', 'exclude', B_path)
2466
2467  # Update to depth 'empty' for the excluded path A/B
2468  expected_output = svntest.wc.State(wc_dir, {
2469    'A/B'         : Item(status='A '),
2470    })
2471  expected_status.add({
2472    'A/B'         : Item(status='  ', wc_rev=1)
2473    })
2474  expected_disk.add({
2475    'A/B'         : Item(contents=None),
2476    })
2477  svntest.actions.run_and_verify_update(wc_dir,
2478                                        expected_output,
2479                                        expected_disk,
2480                                        expected_status,
2481                                        [], False,
2482                                        '--set-depth', 'empty', B_path)
2483  verify_depth(None, "empty", B_path)
2484  expected_info = {
2485      'Path' : re.escape(B_path),
2486      'Repository Root' : sbox.repo_url,
2487      'Repository UUID' : svntest.actions.get_wc_uuid(wc_dir),
2488      'Depth' : 'empty',
2489  }
2490  svntest.actions.run_and_verify_info([expected_info], B_path)
2491
2492  # Exclude A/B again
2493  svntest.actions.run_and_verify_svn(None, [],
2494                                     'up', '--set-depth', 'exclude', B_path)
2495
2496  # Update to depth 'files' for the excluded path A/B
2497  expected_output = svntest.wc.State(wc_dir, {
2498    'A/B'              : Item(status='A '),
2499    'A/B/lambda'       : Item(status='A '),
2500    })
2501  expected_status.add({
2502    'A/B'              : Item(status='  ', wc_rev=1),
2503    'A/B/lambda'       : Item(status='  ', wc_rev=1),
2504    })
2505  expected_disk.add({
2506    'A/B'            : Item(contents=None),
2507    'A/B/lambda'     : Item(contents="This is the file 'lambda'.\n"),
2508    })
2509  svntest.actions.run_and_verify_update(wc_dir,
2510                                        expected_output,
2511                                        expected_disk,
2512                                        expected_status,
2513                                        [], False,
2514                                        '--set-depth', 'files', B_path)
2515  verify_depth(None, "files", B_path)
2516  expected_info = {
2517      'Path' : re.escape(B_path),
2518      'Repository Root' : sbox.repo_url,
2519      'Repository UUID' : svntest.actions.get_wc_uuid(wc_dir),
2520      'Depth' : 'files',
2521  }
2522  svntest.actions.run_and_verify_info([expected_info], B_path)
2523
2524  # Exclude A/B again
2525  svntest.actions.run_and_verify_svn(None, [],
2526                                     'up', '--set-depth', 'exclude', B_path)
2527
2528  # Update to depth 'immediates' for the excluded path A/B
2529  expected_output = svntest.wc.State(wc_dir, {
2530    'A/B'              : Item(status='A '),
2531    'A/B/lambda'       : Item(status='A '),
2532    'A/B/E'            : Item(status='A '),
2533    'A/B/F'            : Item(status='A '),
2534    })
2535  expected_status.add({
2536    'A/B'              : Item(status='  ', wc_rev=1),
2537    'A/B/lambda'       : Item(status='  ', wc_rev=1),
2538    'A/B/E'            : Item(status='  ', wc_rev=1),
2539    'A/B/F'            : Item(status='  ', wc_rev=1),
2540    })
2541  expected_disk.add({
2542    'A/B'              : Item(contents=None),
2543    'A/B/lambda'       : Item(contents="This is the file 'lambda'.\n"),
2544    'A/B/E'            : Item(contents=None),
2545    'A/B/F'            : Item(contents=None),
2546    })
2547  svntest.actions.run_and_verify_update(wc_dir,
2548                                        expected_output,
2549                                        expected_disk,
2550                                        expected_status,
2551                                        [], False,
2552                                        '--set-depth', 'immediates', B_path)
2553  verify_depth(None, "immediates", B_path)
2554  expected_info = {
2555      'Path' : re.escape(B_path),
2556      'Repository Root' : sbox.repo_url,
2557      'Repository UUID' : svntest.actions.get_wc_uuid(wc_dir),
2558      'Depth' : 'immediates',
2559  }
2560  svntest.actions.run_and_verify_info([expected_info], B_path)
2561
2562  # Exclude A/B again
2563  svntest.actions.run_and_verify_svn(None, [],
2564                                     'up', '--set-depth', 'exclude', B_path)
2565
2566  # Update to depth 'infinity' for the excluded path A/B
2567  expected_output = svntest.wc.State(wc_dir, {
2568    'A/B'              : Item(status='A '),
2569    'A/B/lambda'       : Item(status='A '),
2570    'A/B/E'            : Item(status='A '),
2571    'A/B/E/beta'       : Item(status='A '),
2572    'A/B/E/alpha'      : Item(status='A '),
2573    'A/B/F'            : Item(status='A '),
2574    })
2575  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2576  expected_disk = svntest.main.greek_state.copy()
2577  svntest.actions.run_and_verify_update(wc_dir,
2578                                        expected_output,
2579                                        expected_disk,
2580                                        expected_status,
2581                                        [], False,
2582                                        '--set-depth', 'infinity', B_path)
2583  verify_depth(None, "infinity", B_path)
2584  expected_info = {
2585      'Path' : re.escape(B_path),
2586      'Repository Root' : sbox.repo_url,
2587      'Repository UUID' : svntest.actions.get_wc_uuid(wc_dir),
2588  #   'Depth' value is absent for 'infinity'
2589  }
2590  svntest.actions.run_and_verify_info([expected_info], B_path)
2591
2592
2593def update_depth_empty_root_of_infinite_children(sbox):
2594  """update depth=empty root of depth=infinite children"""
2595
2596  wc_dir, ign_a, ign_b, wc_other = set_up_depthy_working_copies(sbox,
2597                                                                empty=True,
2598                                                                infinity=True)
2599  A_path = os.path.join(wc_dir, 'A')
2600
2601  # Update A to depth 'infinity'
2602  svntest.actions.run_and_verify_svn(None, [],
2603                                     'up', '--set-depth', 'infinity', A_path)
2604
2605  # Tweak some files in the full working copy and commit.
2606  svntest.main.file_append(os.path.join(wc_other, 'A', 'B', 'E', 'alpha'),
2607                           "Modified alpha.\n")
2608  svntest.main.file_append(os.path.join(wc_other, 'A', 'D', 'G', 'rho'),
2609                           "Modified rho.\n")
2610  svntest.actions.run_and_verify_svn(None, [],
2611                                     'ci', '-m', '', wc_other)
2612
2613  # Now update the original working copy and make sure we get those changes.
2614  expected_output = svntest.wc.State(wc_dir, {
2615    'A/B/E/alpha'      : Item(status='U '),
2616    'A/D/G/rho'        : Item(status='U '),
2617    })
2618  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
2619  expected_status.remove('iota')
2620  expected_disk = svntest.main.greek_state.copy()
2621  expected_disk.remove('iota')
2622  expected_disk.tweak('A/B/E/alpha', contents="This is the file 'alpha'.\nModified alpha.\n")
2623  expected_disk.tweak('A/D/G/rho', contents="This is the file 'rho'.\nModified rho.\n")
2624  svntest.actions.run_and_verify_update(wc_dir,
2625                                        expected_output,
2626                                        expected_disk,
2627                                        expected_status)
2628
2629def sparse_update_with_dash_dash_parents(sbox):
2630  """update --parents"""
2631
2632  sbox.build(create_wc = False)
2633  sbox.add_test_path(sbox.wc_dir, True)
2634  alpha_path = sbox.ospath('A/B/E/alpha')
2635  pi_path = sbox.ospath('A/D/G/pi')
2636  omega_path = sbox.ospath('A/D/H/omega')
2637
2638  # Start with a depth=empty root checkout.
2639  svntest.actions.run_and_verify_svn(
2640      svntest.verify.AnyOutput, [],
2641      "co", "--depth", "empty", sbox.repo_url, sbox.wc_dir)
2642
2643  # Now, let's use --parents to pull in some scattered file children.
2644  expected_output = svntest.wc.State(sbox.wc_dir, {
2645    'A'            : Item(status='A '),
2646    'A/B'          : Item(status='A '),
2647    'A/B/E'        : Item(status='A '),
2648    'A/B/E/alpha'  : Item(status='A '),
2649    })
2650  expected_disk = svntest.wc.State('', {
2651    'A'            : Item(contents=None),
2652    'A/B'          : Item(contents=None),
2653    'A/B/E'        : Item(contents=None),
2654    'A/B/E/alpha'  : Item(contents="This is the file 'alpha'.\n"),
2655    })
2656  expected_status = svntest.wc.State(sbox.wc_dir, {
2657    ''             : Item(status='  ', wc_rev=1),
2658    'A'            : Item(status='  ', wc_rev=1),
2659    'A/B'          : Item(status='  ', wc_rev=1),
2660    'A/B/E'        : Item(status='  ', wc_rev=1),
2661    'A/B/E/alpha'  : Item(status='  ', wc_rev=1),
2662    })
2663  svntest.actions.run_and_verify_update(sbox.wc_dir,
2664                                        expected_output,
2665                                        expected_disk,
2666                                        expected_status,
2667                                        [], False,
2668                                        '--parents', alpha_path)
2669
2670  expected_output = svntest.wc.State(sbox.wc_dir, {
2671    'A/D'          : Item(status='A '),
2672    'A/D/G'        : Item(status='A '),
2673    'A/D/G/pi'     : Item(status='A '),
2674    })
2675  expected_disk.add({
2676    'A/D'          : Item(contents=None),
2677    'A/D/G'        : Item(contents=None),
2678    'A/D/G/pi'     : Item(contents="This is the file 'pi'.\n"),
2679    })
2680  expected_status.add({
2681    'A/D'          : Item(status='  ', wc_rev=1),
2682    'A/D/G'        : Item(status='  ', wc_rev=1),
2683    'A/D/G/pi'     : Item(status='  ', wc_rev=1),
2684    })
2685  svntest.actions.run_and_verify_update(sbox.wc_dir,
2686                                        expected_output,
2687                                        expected_disk,
2688                                        expected_status,
2689                                        [], False,
2690                                        '--parents', pi_path)
2691
2692  expected_output = svntest.wc.State(sbox.wc_dir, {
2693    'A/D/H'        : Item(status='A '),
2694    'A/D/H/omega'  : Item(status='A '),
2695    })
2696  expected_disk.add({
2697    'A/D/H'        : Item(contents=None),
2698    'A/D/H/omega'  : Item(contents="This is the file 'omega'.\n"),
2699    })
2700  expected_status.add({
2701    'A/D/H'        : Item(status='  ', wc_rev=1),
2702    'A/D/H/omega'  : Item(status='  ', wc_rev=1),
2703    })
2704  svntest.actions.run_and_verify_update(sbox.wc_dir,
2705                                        expected_output,
2706                                        expected_disk,
2707                                        expected_status,
2708                                        [], False,
2709                                        '--parents', omega_path)
2710
2711def update_below_depth_empty(sbox):
2712  "update below depth empty shouldn't be applied"
2713  sbox.build()
2714
2715  repo_url = sbox.repo_url
2716  A = sbox.ospath('A')
2717
2718  expected_output = svntest.wc.State(sbox.wc_dir, {
2719      'A/C'               : Item(status='D '),
2720      'A/B'               : Item(status='D '),
2721      'A/mu'              : Item(status='D '),
2722      'A/D'               : Item(status='D '),
2723    })
2724  svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output, None,
2725                                        None,
2726                                        [], False,
2727                                        '--set-depth', 'empty', A)
2728
2729  svntest.actions.run_and_verify_svn(None, [],
2730                                     'cp', repo_url + '/iota',
2731                                           repo_url + '/A/B',
2732                                     '-m', 'remote copy')
2733
2734  expected_output = svntest.wc.State(sbox.wc_dir, {
2735    })
2736
2737  # This update should just update the revision of the working copy
2738  svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output, None,
2739                                        None)
2740
2741# Test for issue #4136.
2742@Issue(4136)
2743def commit_then_immediates_update(sbox):
2744  "deep commit followed by update --depth immediates"
2745  sbox.build()
2746
2747  repo_url = sbox.repo_url
2748  wc_dir = sbox.wc_dir
2749  mu_path = sbox.ospath('A/mu')
2750
2751  # Modify A/mu and commit the changes.
2752  svntest.main.file_write(mu_path, "modified mu\n")
2753  expected_output = svntest.wc.State(wc_dir, {
2754    'A/mu'        : Item(verb='Sending'),
2755    })
2756  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2757  expected_status.tweak('A/mu', wc_rev=2, status='  ')
2758  svntest.actions.run_and_verify_commit(wc_dir,
2759                                        expected_output,
2760                                        expected_status)
2761
2762  # Now, update --depth immediates in the root of the working copy.
2763  expected_output = svntest.wc.State(wc_dir, { })
2764  expected_disk = svntest.main.greek_state.copy()
2765  expected_disk.tweak('A/mu', contents="modified mu\n")
2766  expected_status = svntest.wc.State(wc_dir, { '' : svntest.wc.StateItem() })
2767  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2768  expected_status.tweak('',     wc_rev=2, status='  ')
2769  expected_status.tweak('A',    wc_rev=2, status='  ')
2770  expected_status.tweak('A/mu', wc_rev=2, status='  ')
2771  expected_status.tweak('iota', wc_rev=2, status='  ')
2772  svntest.actions.run_and_verify_update(wc_dir,
2773                                        expected_output,
2774                                        expected_disk,
2775                                        expected_status,
2776                                        [], False,
2777                                        "--depth=immediates", wc_dir)
2778
2779def revert_depth_files(sbox):
2780  "depth immediate+files should revert deleted files"
2781
2782  sbox.build(read_only = True)
2783
2784  expected_output = "Reverted '" + re.escape(sbox.ospath('A/mu')) + "'"
2785
2786  # Apply an unrelated delete one level to deep
2787  sbox.simple_rm('A/D/gamma')
2788
2789  sbox.simple_rm('A/mu')
2790  # Expect reversion of just 'mu'
2791  svntest.actions.run_and_verify_svn(expected_output, [],
2792                                     'revert', '--depth=immediates', sbox.ospath('A'))
2793
2794  # Apply an unrelated directory delete
2795  sbox.simple_rm('A/D')
2796
2797  sbox.simple_rm('A/mu')
2798  # Expect reversion of just 'mu'
2799  svntest.actions.run_and_verify_svn(expected_output, [],
2800                                     'revert', '--depth=files', sbox.ospath('A'))
2801
2802@Issue(4257)
2803def spurious_nodes_row(sbox):
2804  "update produces no spurious rows"
2805
2806  sbox.build(read_only = True)
2807  return
2808
2809  val1 = svntest.wc.sqlite_stmt(sbox.wc_dir, "select count(*) from nodes")
2810  expected_output = svntest.wc.State(sbox.wc_dir, { })
2811  expected_disk = svntest.main.greek_state.copy()
2812  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
2813  svntest.actions.run_and_verify_update(sbox.wc_dir,
2814                                        expected_output,
2815                                        expected_disk,
2816                                        expected_status,
2817                                        [], False,
2818                                        "--depth=empty", sbox.wc_dir)
2819  val2 = svntest.wc.sqlite_stmt(sbox.wc_dir, "select count(*) from nodes")
2820  if (val1 != val2):
2821    # ra_neon added a spurious not-present row that does not show up in status
2822    raise svntest.Failure("count changed from '%s' to '%s'" % (val1, val2))
2823
2824def commit_excluded(sbox):
2825  "commit an excluded node"
2826
2827  sbox.build()
2828  wc_dir = sbox.wc_dir
2829
2830  expected_output = svntest.wc.State(wc_dir, {
2831    'A/D/G' : Item(status='D '),
2832  })
2833  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2834  expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
2835
2836  svntest.actions.run_and_verify_update(wc_dir,
2837                                        expected_output,
2838                                        None,
2839                                        expected_status,
2840                                        [], False,
2841                                        "--set-depth=exclude",
2842                                        sbox.ospath('A/D/G'))
2843
2844  sbox.simple_copy('A/D', 'D')
2845
2846  expected_output = svntest.wc.State(wc_dir, {
2847    'D' : Item(verb='Adding'),
2848  })
2849
2850  expected_status.add({
2851    'D'          : Item(status='  ', wc_rev='2'),
2852    'D/H'        : Item(status='  ', wc_rev='2'),
2853    'D/H/chi'    : Item(status='  ', wc_rev='2'),
2854    'D/H/psi'    : Item(status='  ', wc_rev='2'),
2855    'D/H/omega'  : Item(status='  ', wc_rev='2'),
2856    'D/gamma'    : Item(status='  ', wc_rev='2')
2857  })
2858
2859  svntest.actions.run_and_verify_commit(wc_dir,
2860                                        expected_output,
2861                                        expected_status)
2862
2863  expected_output = svntest.wc.State(wc_dir, {
2864    'A/D/G'     : Item(status='A '),
2865    'A/D/G/pi'  : Item(status='A '),
2866    'A/D/G/tau' : Item(status='A '),
2867    'A/D/G/rho' : Item(status='A '),
2868    'D/G'       : Item(status='A '),
2869    'D/G/pi'    : Item(status='A '),
2870    'D/G/tau'   : Item(status='A '),
2871    'D/G/rho'   : Item(status='A ')
2872  })
2873
2874  expected_status.tweak(wc_rev=2)
2875
2876  expected_status.add({
2877    'D'         : Item(status='  ', wc_rev='2'),
2878    'D/G'       : Item(status='  ', wc_rev='2'),
2879    'D/G/pi'    : Item(status='  ', wc_rev='2'),
2880    'D/G/rho'   : Item(status='  ', wc_rev='2'),
2881    'D/G/tau'   : Item(status='  ', wc_rev='2'),
2882    'D/H'       : Item(status='  ', wc_rev='2'),
2883    'D/H/chi'   : Item(status='  ', wc_rev='2'),
2884    'D/H/psi'   : Item(status='  ', wc_rev='2'),
2885    'D/H/omega' : Item(status='  ', wc_rev='2'),
2886    'D/gamma'   : Item(status='  ', wc_rev='2'),
2887    'A/D/G'     : Item(status='  ', wc_rev='2'),
2888    'A/D/G/rho' : Item(status='  ', wc_rev='2'),
2889    'A/D/G/tau' : Item(status='  ', wc_rev='2'),
2890    'A/D/G/pi'  : Item(status='  ', wc_rev='2')
2891  })
2892
2893  svntest.actions.run_and_verify_update(wc_dir,
2894                                        expected_output,
2895                                        None,
2896                                        expected_status,
2897                                        [], False,
2898                                        "--set-depth=infinity", wc_dir)
2899
2900@Issue(4636)
2901@XFail()
2902def fold_tree_with_deleted_moved_items(sbox):
2903  "deleted & moved items left untouched"
2904  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
2905                                                             infinity=True)
2906
2907  A_path = sbox.ospath('A')
2908
2909  # Delete file lambda, move file pi and directory C
2910  sbox.simple_rm('A/B/lambda')
2911  sbox.simple_move('A/D/G/pi', 'A/D/G/pi_moved')
2912  sbox.simple_move('A/C', 'A/C_moved')
2913
2914  # Fold the A dir to empty, expect the deleted & moved items ones left
2915  # and visible in status, rather than gone without a trace.
2916
2917  # Directories B and D won't be deleted, because that would remove their
2918  # local modifications. Their unmodified descendants are deleted though.
2919  expected_output = svntest.wc.State(wc_dir, {
2920    'A/B/E'          : Item(status='D '),
2921    'A/B/F'          : Item(status='D '),
2922    'A/D/G/rho'      : Item(status='D '),
2923    'A/D/G/tau'      : Item(status='D '),
2924    'A/D/H'          : Item(status='D '),
2925    'A/D/gamma'      : Item(status='D '),
2926    'A/mu'           : Item(status='D '),
2927    })
2928  expected_status = svntest.wc.State(wc_dir, {
2929    ''               : Item(status='  ', wc_rev=1),
2930    'iota'           : Item(status='  ', wc_rev=1),
2931    'A'              : Item(status='  ', wc_rev=1),
2932    'A/B'            : Item(status='  ', wc_rev=1),
2933    'A/B/lambda'     : Item(status='D ', wc_rev=1),
2934    'A/C'            : Item(status='D ', wc_rev=1, moved_to='A/C_moved'),
2935    'A/C_moved'      : Item(status='A ', wc_rev='-', copied='+',
2936                            moved_from='A/C'),
2937    'A/D'            : Item(status='  ', wc_rev=1),
2938    'A/D/G'          : Item(status='  ', wc_rev=1),
2939    'A/D/G/pi'       : Item(status='D ', wc_rev=1, moved_to='A/D/G/pi_moved'),
2940    'A/D/G/pi_moved' : Item(status='A ', wc_rev='-', copied='+',
2941                            moved_from='A/D/G/pi'),
2942    })
2943  expected_disk = svntest.wc.State('', {
2944    'iota'           : Item(contents="This is the file 'iota'.\n"),
2945    'A'              : Item(contents=None),
2946    'A/B'            : Item(contents=None),
2947    'A/C_moved'      : Item(contents=None),
2948    'A/D'            : Item(contents=None),
2949    'A/D/G'          : Item(contents=None),
2950    'A/D/G/pi_moved' : Item(contents="This is the file 'pi'.\n"),
2951    })
2952  svntest.actions.run_and_verify_update(wc_dir,
2953                                        expected_output,
2954                                        expected_disk,
2955                                        expected_status,
2956                                        [], False,
2957                                        '--set-depth', 'empty', A_path)
2958  verify_depth(None, "empty", A_path)
2959
2960@Issue(4642)
2961@XFail()
2962def fold_tree_with_unversioned_items(sbox):
2963  "unversioned files in excluded directory"
2964  ign_a, ign_b, ign_c, wc_dir = set_up_depthy_working_copies(sbox,
2965                                                             infinity=True)
2966
2967  # create an unversioned directory within a versioned one
2968  A_path = sbox.ospath('A')
2969  A_local_path = os.path.join(A_path, 'A_local')
2970  os.mkdir(A_local_path)
2971
2972  # Set A to be excluded.
2973  svntest.main.run_svn(None, 'update', '--set-depth=exclude', A_path)
2974
2975  # try a simple update afterwards
2976  sbox.simple_update()
2977
2978#----------------------------------------------------------------------
2979# list all tests here, starting with None:
2980test_list = [ None,
2981              depth_empty_checkout,
2982              depth_files_checkout,
2983              nonrecursive_checkout,
2984              depth_empty_update_bypass_single_file,
2985              depth_immediates_get_top_file_mod_only,
2986              depth_empty_commit,
2987              depth_empty_with_file,
2988              depth_empty_with_dir,
2989              depth_immediates_bring_in_file,
2990              depth_immediates_fill_in_dir,
2991              depth_mixed_bring_in_dir,
2992              depth_empty_unreceive_delete,
2993              depth_immediates_unreceive_delete,
2994              depth_immediates_receive_delete,
2995              depth_update_to_more_depth,
2996              depth_immediates_subdir_propset_1,
2997              depth_immediates_subdir_propset_2,
2998              commit_propmods_with_depth_empty,
2999              diff_in_depthy_wc,
3000              commit_depth_immediates,
3001              depth_immediates_receive_new_dir,
3002              add_tree_with_depth,
3003              upgrade_from_above,
3004              status_in_depthy_wc,
3005              depthy_update_above_dir_to_be_deleted,
3006              depth_folding_clean_trees_1,
3007              depth_folding_clean_trees_2,
3008              depth_fold_expand_clean_trees,
3009              pull_in_tree_with_depth_option,
3010              fold_tree_with_unversioned_modified_items,
3011              depth_empty_update_on_file,
3012              excluded_path_update_operation,
3013              excluded_path_misc_operation,
3014              excluded_receive_remote_removal,
3015              exclude_keeps_hidden_entries,
3016              info_excluded,
3017              tree_conflicts_resolved_depth_empty,
3018              tree_conflicts_resolved_depth_files,
3019              tree_conflicts_resolved_depth_immediates,
3020              tree_conflicts_resolved_depth_infinity,
3021              update_excluded_path_sticky_depths,
3022              update_depth_empty_root_of_infinite_children,
3023              sparse_update_with_dash_dash_parents,
3024              update_below_depth_empty,
3025              commit_then_immediates_update,
3026              revert_depth_files,
3027              spurious_nodes_row,
3028              commit_excluded,
3029              fold_tree_with_deleted_moved_items,
3030              fold_tree_with_unversioned_items,
3031             ]
3032
3033if __name__ == "__main__":
3034  svntest.main.run_tests(test_list)
3035  # NOTREACHED
3036
3037
3038### End of file.
3039