~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/tests/clients/cmdline/update_tests.py

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
#
 
3
#  update_tests.py:  testing update cases.
 
4
#
 
5
#  Subversion is a tool for revision control. 
 
6
#  See http://subversion.tigris.org for more information.
 
7
#    
 
8
# ====================================================================
 
9
# Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 
10
#
 
11
# This software is licensed as described in the file COPYING, which
 
12
# you should have received as part of this distribution.  The terms
 
13
# are also available at http://subversion.tigris.org/license-1.html.
 
14
# If newer versions of this license are posted there, you may use a
 
15
# newer version instead, at your option.
 
16
#
 
17
######################################################################
 
18
 
 
19
# General modules
 
20
import shutil, string, sys, re, os
 
21
 
 
22
# Our testing module
 
23
import svntest
 
24
from svntest import wc, SVNAnyOutput
 
25
 
 
26
 
 
27
# (abbreviation)
 
28
Skip = svntest.testcase.Skip
 
29
XFail = svntest.testcase.XFail
 
30
Item = svntest.wc.StateItem
 
31
 
 
32
 
 
33
######################################################################
 
34
# Tests
 
35
#
 
36
#   Each test must return on success or raise on failure.
 
37
 
 
38
 
 
39
#----------------------------------------------------------------------
 
40
 
 
41
# Helper for update_binary_file() test -- a custom singleton handler.
 
42
def detect_extra_files(node, extra_files):
 
43
  """NODE has been discovered as an extra file on disk.  Verify that
 
44
  it matches one of the regular expressions in the EXTRA_FILES list of
 
45
  lists, and that its contents matches the second part of the list
 
46
  item.  If it matches, remove the match from the list.  If it doesn't
 
47
  match, raise an exception."""
 
48
 
 
49
  # Baton is of the form:
 
50
  #
 
51
  #       [ [wc_dir, pattern, contents],
 
52
  #         [wc_dir, pattern, contents], ... ]
 
53
 
 
54
  for fdata in extra_files:
 
55
    wc_dir = fdata[0]
 
56
    pattern = fdata[1]
 
57
    contents = None
 
58
    if len(fdata) > 2:
 
59
      contents = fdata[2]
 
60
    match_obj = re.match(pattern, node.name)
 
61
    if match_obj:
 
62
      if contents is None:
 
63
        return
 
64
      else:
 
65
        fp = open(os.path.join (wc_dir, node.path))
 
66
        real_contents = fp.read()  # suck up contents of a test .png file
 
67
        fp.close()
 
68
        if real_contents == contents:
 
69
          extra_files.pop(extra_files.index(fdata)) # delete pattern from list
 
70
          return
 
71
 
 
72
  print "Found unexpected object:", node.name
 
73
  raise svntest.main.SVNTreeUnequal
 
74
 
 
75
 
 
76
 
 
77
def update_binary_file(sbox):
 
78
  "update a locally-modified binary file"
 
79
 
 
80
  sbox.build()
 
81
  wc_dir = sbox.wc_dir
 
82
 
 
83
  # Add a binary file to the project.
 
84
  fp = open(os.path.join(sys.path[0], "theta.bin"))
 
85
  theta_contents = fp.read()  # suck up contents of a test .png file
 
86
  fp.close()
 
87
 
 
88
  theta_path = os.path.join(wc_dir, 'A', 'theta')
 
89
  fp = open(theta_path, 'w')
 
90
  fp.write(theta_contents)    # write png filedata into 'A/theta'
 
91
  fp.close()
 
92
  
 
93
  svntest.main.run_svn(None, 'add', theta_path)  
 
94
 
 
95
  # Created expected output tree for 'svn ci'
 
96
  expected_output = svntest.wc.State(wc_dir, {
 
97
    'A/theta' : Item(verb='Adding  (bin)'),
 
98
    })
 
99
 
 
100
  # Create expected status tree
 
101
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
102
  expected_status.tweak(wc_rev=1)
 
103
  expected_status.add({
 
104
    'A/theta' : Item(status='  ', wc_rev=2),
 
105
    })
 
106
 
 
107
  # Commit the new binary file, creating revision 2.
 
108
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
109
                                        expected_status, None,
 
110
                                        None, None, None, None, wc_dir)
 
111
 
 
112
  # Make a backup copy of the working copy.
 
113
  wc_backup = sbox.add_wc_path('backup')
 
114
  svntest.actions.duplicate_dir(wc_dir, wc_backup)
 
115
  theta_backup_path = os.path.join(wc_backup, 'A', 'theta')
 
116
 
 
117
  # Make a change to the binary file in the original working copy
 
118
  svntest.main.file_append(theta_path, "revision 3 text")
 
119
  theta_contents_r3 = theta_contents + "revision 3 text"
 
120
 
 
121
  # Created expected output tree for 'svn ci'
 
122
  expected_output = svntest.wc.State(wc_dir, {
 
123
    'A/theta' : Item(verb='Sending'),
 
124
    })
 
125
 
 
126
  # Create expected status tree
 
127
  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
 
128
  expected_status.tweak(wc_rev=1)
 
129
  expected_status.add({
 
130
    'A/theta' : Item(status='  ', wc_rev=3),
 
131
    })
 
132
 
 
133
  # Commit original working copy again, creating revision 3.
 
134
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
135
                                        expected_status, None,
 
136
                                        None, None, None, None, wc_dir)
 
137
 
 
138
  # Now start working in the backup working copy:
 
139
 
 
140
  # Make a local mod to theta
 
141
  svntest.main.file_append(theta_backup_path, "extra theta text")
 
142
  theta_contents_local = theta_contents + "extra theta text"
 
143
 
 
144
  # Create expected output tree for an update of wc_backup.
 
145
  expected_output = svntest.wc.State(wc_backup, {
 
146
    'A/theta' : Item(status='C '),
 
147
    })
 
148
 
 
149
  # Create expected disk tree for the update -- 
 
150
  #    look!  binary contents, and a binary property!
 
151
  expected_disk = svntest.main.greek_state.copy()
 
152
  expected_disk.add({
 
153
    'A/theta' : Item(theta_contents_local,
 
154
                     props={'svn:mime-type' : 'application/octet-stream'}),
 
155
    })
 
156
 
 
157
  # Create expected status tree for the update.
 
158
  expected_status = svntest.actions.get_virginal_state(wc_backup, 3)
 
159
  expected_status.add({
 
160
    'A/theta' : Item(status='C ', wc_rev=3),
 
161
    })
 
162
 
 
163
  # Extra 'singleton' files we expect to exist after the update.
 
164
  # In the case, the locally-modified binary file should be backed up
 
165
  # to an .orig file.
 
166
  #  This is a list of lists, of the form [ WC_DIR,
 
167
  #                                         [pattern, contents], ...]
 
168
  extra_files = [[wc_backup, 'theta.*\.r2', theta_contents],
 
169
                 [wc_backup, 'theta.*\.r3', theta_contents_r3]]
 
170
  
 
171
  # Do the update and check the results in three ways.  Pass our
 
172
  # custom singleton handler to verify the .orig file; this handler
 
173
  # will verify the existence (and contents) of both binary files
 
174
  # after the update finishes.
 
175
  svntest.actions.run_and_verify_update(wc_backup,
 
176
                                        expected_output,
 
177
                                        expected_disk,
 
178
                                        expected_status,
 
179
                                        None,
 
180
                                        detect_extra_files, extra_files,
 
181
                                        None, None, 1)
 
182
 
 
183
  # verify that the extra_files list is now empty.
 
184
  if len(extra_files) != 0:
 
185
    print "Not all extra reject files have been accounted for:"
 
186
    print extra_files
 
187
    raise svntest.Failure
 
188
 
 
189
#----------------------------------------------------------------------
 
190
 
 
191
def update_binary_file_2(sbox):
 
192
  "update to an old revision of a binary files"
 
193
 
 
194
  sbox.build()
 
195
  wc_dir = sbox.wc_dir
 
196
 
 
197
  # Suck up contents of a test .png file.
 
198
  fp = open(os.path.join(sys.path[0], "theta.bin"))
 
199
  theta_contents = fp.read()  
 
200
  fp.close()
 
201
 
 
202
  # 102400 is svn_txdelta_window_size.  We're going to make sure we
 
203
  # have at least 102401 bytes of data in our second binary file (for
 
204
  # no reason other than we have had problems in the past with getting
 
205
  # svndiff data out of the repository for files > 102400 bytes).
 
206
  # How?  Well, we'll just keep doubling the binary contents of the
 
207
  # original theta.png until we're big enough.
 
208
  zeta_contents = theta_contents
 
209
  while(len(zeta_contents) < 102401):
 
210
    zeta_contents = zeta_contents + zeta_contents
 
211
 
 
212
  # Write our two files' contents out to disk, in A/theta and A/zeta.
 
213
  theta_path = os.path.join(wc_dir, 'A', 'theta')
 
214
  fp = open(theta_path, 'w')
 
215
  fp.write(theta_contents)    
 
216
  fp.close()
 
217
  zeta_path = os.path.join(wc_dir, 'A', 'zeta')
 
218
  fp = open(zeta_path, 'w')
 
219
  fp.write(zeta_contents)
 
220
  fp.close()
 
221
 
 
222
  # Now, `svn add' those two files.
 
223
  svntest.main.run_svn(None, 'add', theta_path, zeta_path)  
 
224
 
 
225
  # Created expected output tree for 'svn ci'
 
226
  expected_output = svntest.wc.State(wc_dir, {
 
227
    'A/theta' : Item(verb='Adding  (bin)'),
 
228
    'A/zeta' : Item(verb='Adding  (bin)'),
 
229
    })
 
230
 
 
231
  # Create expected status tree
 
232
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
233
  expected_status.tweak(wc_rev=1)
 
234
  expected_status.add({
 
235
    'A/theta' : Item(status='  ', wc_rev=2),
 
236
    'A/zeta' : Item(status='  ', wc_rev=2),
 
237
    })
 
238
 
 
239
  # Commit the new binary filea, creating revision 2.
 
240
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
241
                                        expected_status, None,
 
242
                                        None, None, None, None, wc_dir)
 
243
 
 
244
  # Make some mods to the binary files.
 
245
  svntest.main.file_append (theta_path, "foobar")
 
246
  new_theta_contents = theta_contents + "foobar"
 
247
  svntest.main.file_append (zeta_path, "foobar")
 
248
  new_zeta_contents = zeta_contents + "foobar"
 
249
  
 
250
  # Created expected output tree for 'svn ci'
 
251
  expected_output = svntest.wc.State(wc_dir, {
 
252
    'A/theta' : Item(verb='Sending'),
 
253
    'A/zeta' : Item(verb='Sending'),
 
254
    })
 
255
 
 
256
  # Create expected status tree
 
257
  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
 
258
  expected_status.tweak(wc_rev=1)
 
259
  expected_status.add({
 
260
    'A/theta' : Item(status='  ', wc_rev=3),
 
261
    'A/zeta' : Item(status='  ', wc_rev=3),
 
262
    })
 
263
 
 
264
  # Commit original working copy again, creating revision 3.
 
265
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
266
                                        expected_status, None,
 
267
                                        None, None, None, None, wc_dir)
 
268
 
 
269
  # Create expected output tree for an update to rev 2.
 
270
  expected_output = svntest.wc.State(wc_dir, {
 
271
    'A/theta' : Item(status='U '),
 
272
    'A/zeta' : Item(status='U '),
 
273
    })
 
274
 
 
275
  # Create expected disk tree for the update -- 
 
276
  #    look!  binary contents, and a binary property!
 
277
  expected_disk = svntest.main.greek_state.copy()
 
278
  expected_disk.add({
 
279
    'A/theta' : Item(theta_contents,
 
280
                     props={'svn:mime-type' : 'application/octet-stream'}),
 
281
    'A/zeta' : Item(zeta_contents,
 
282
                    props={'svn:mime-type' : 'application/octet-stream'}),
 
283
    })
 
284
 
 
285
  # Create expected status tree for the update.
 
286
  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
 
287
  expected_status.tweak(wc_rev=2)
 
288
  expected_status.add({
 
289
    'A/theta' : Item(status='  ', wc_rev=2),
 
290
    'A/zeta' : Item(status='  ', wc_rev=2),
 
291
    })
 
292
 
 
293
  # Do an update from revision 2 and make sure that our binary file
 
294
  # gets reverted to its original contents.
 
295
  svntest.actions.run_and_verify_update(wc_dir,
 
296
                                        expected_output,
 
297
                                        expected_disk,
 
298
                                        expected_status,
 
299
                                        None, None, None,
 
300
                                        None, None, 1,
 
301
                                        '-r', '2', wc_dir)
 
302
 
 
303
 
 
304
#----------------------------------------------------------------------
 
305
 
 
306
def update_missing(sbox):
 
307
  "update missing items (by name) in working copy"
 
308
 
 
309
  sbox.build()
 
310
  wc_dir = sbox.wc_dir
 
311
 
 
312
  # Remove some files and dirs from the working copy.
 
313
  mu_path = os.path.join(wc_dir, 'A', 'mu')
 
314
  rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
 
315
  E_path = os.path.join(wc_dir, 'A', 'B', 'E')
 
316
  H_path = os.path.join(wc_dir, 'A', 'D', 'H')
 
317
 
 
318
  # remove two files to verify that they get restored
 
319
  os.remove(mu_path)
 
320
  os.remove(rho_path)
 
321
 
 
322
  ### FIXME I think directories work because they generate 'A'
 
323
  ### feedback, is this the correct feedback?
 
324
  svntest.main.safe_rmtree(E_path)
 
325
  svntest.main.safe_rmtree(H_path)
 
326
 
 
327
  # Create expected output tree for an update of the missing items by name
 
328
  expected_output = svntest.wc.State(wc_dir, {
 
329
    'A/mu'        : Item(verb='Restored'),
 
330
    'A/D/G/rho'   : Item(verb='Restored'),
 
331
    'A/B/E' : Item(status='A '),
 
332
    'A/B/E/alpha' : Item(status='A '),
 
333
    'A/B/E/beta' : Item(status='A '),
 
334
    'A/D/H' : Item(status='A '),
 
335
    'A/D/H/chi' : Item(status='A '),
 
336
    'A/D/H/omega' : Item(status='A '),
 
337
    'A/D/H/psi' : Item(status='A '),
 
338
    })
 
339
 
 
340
  # Create expected disk tree for the update.
 
341
  expected_disk = svntest.main.greek_state.copy()
 
342
 
 
343
  # Create expected status tree for the update.
 
344
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
 
345
  
 
346
  # Do the update and check the results in three ways.
 
347
  svntest.actions.run_and_verify_update(wc_dir,
 
348
                                        expected_output,
 
349
                                        expected_disk,
 
350
                                        expected_status,
 
351
                                        None, None, None, None, None, 0,
 
352
                                        mu_path, rho_path,
 
353
                                        E_path, H_path)
 
354
 
 
355
#----------------------------------------------------------------------
 
356
 
 
357
def update_ignores_added(sbox):
 
358
  "update should not munge adds or replaces"
 
359
 
 
360
  sbox.build()
 
361
  wc_dir = sbox.wc_dir
 
362
 
 
363
  # Commit something so there's actually a new revision to update to.
 
364
  rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
 
365
  svntest.main.file_append(rho_path, "\nMore stuff in rho.")
 
366
  svntest.main.run_svn(None, 'ci', '-m', 'log msg', rho_path)  
 
367
 
 
368
  # Create a new file, 'zeta', and schedule it for addition.
 
369
  zeta_path = os.path.join(wc_dir, 'A', 'B', 'zeta')
 
370
  svntest.main.file_append(zeta_path, "This is the file 'zeta'.")
 
371
  svntest.main.run_svn(None, 'add', zeta_path)
 
372
 
 
373
  # Schedule another file, say, 'gamma', for replacement.
 
374
  gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma')
 
375
  svntest.main.run_svn(None, 'delete', gamma_path)
 
376
  svntest.main.file_append(gamma_path, "This is a new 'gamma' now.")
 
377
  svntest.main.run_svn(None, 'add', gamma_path)
 
378
  
 
379
  # Now update.  "zeta at revision 0" should *not* be reported at all,
 
380
  # so it should remain scheduled for addition at revision 0.  gamma
 
381
  # was scheduled for replacement, so it also should remain marked as
 
382
  # such, and maintain its revision of 1.
 
383
 
 
384
  # Create expected output tree for an update of the wc_backup.
 
385
  expected_output = svntest.wc.State(wc_dir, { })
 
386
 
 
387
  # Create expected disk tree for the update.
 
388
  expected_disk = svntest.main.greek_state.copy()
 
389
  expected_disk.add({
 
390
    'A/B/zeta' : Item("This is the file 'zeta'."),
 
391
    })
 
392
  expected_disk.tweak('A/D/gamma', contents="This is a new 'gamma' now.")
 
393
  expected_disk.tweak('A/D/G/rho',
 
394
                      contents="This is the file 'rho'.\nMore stuff in rho.")
 
395
 
 
396
  # Create expected status tree for the update.
 
397
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
398
  expected_status.tweak('A/D/gamma', wc_rev=1, status='R ')
 
399
  expected_status.add({
 
400
    'A/B/zeta' : Item(status='A ', wc_rev=0),
 
401
    })
 
402
  
 
403
  # Do the update and check the results in three ways.
 
404
  svntest.actions.run_and_verify_update(wc_dir,
 
405
                                        expected_output,
 
406
                                        expected_disk,
 
407
                                        expected_status)
 
408
  
 
409
 
 
410
#----------------------------------------------------------------------
 
411
 
 
412
def update_to_rev_zero(sbox):
 
413
  "update to revision 0"
 
414
 
 
415
  sbox.build()
 
416
  wc_dir = sbox.wc_dir
 
417
 
 
418
  iota_path = os.path.join(wc_dir, 'iota')
 
419
  A_path = os.path.join(wc_dir, 'A')
 
420
 
 
421
  # Create expected output tree for an update to rev 0
 
422
  expected_output = svntest.wc.State(wc_dir, {
 
423
    'iota' : Item(status='D '),
 
424
    'A' : Item(status='D '),
 
425
    })
 
426
 
 
427
  # Create expected disk tree for the update to rev 0
 
428
  expected_disk = svntest.wc.State(wc_dir, { })
 
429
  
 
430
  # Do the update and check the results.
 
431
  svntest.actions.run_and_verify_update(wc_dir,
 
432
                                        expected_output,
 
433
                                        expected_disk,
 
434
                                        None, None,
 
435
                                        None, None, None, None, 0,
 
436
                                        '-r', '0', wc_dir)
 
437
 
 
438
#----------------------------------------------------------------------
 
439
 
 
440
def receive_overlapping_same_change(sbox):
 
441
  "overlapping identical changes should not conflict"
 
442
 
 
443
  ### (See http://subversion.tigris.org/issues/show_bug.cgi?id=682.)
 
444
  ###
 
445
  ### How this test works:
 
446
  ###
 
447
  ### Create working copy foo, modify foo/iota.  Duplicate foo,
 
448
  ### complete with locally modified iota, to bar.  Now we should
 
449
  ### have:
 
450
  ### 
 
451
  ###    $ svn st foo
 
452
  ###    M    foo/iota
 
453
  ###    $ svn st bar
 
454
  ###    M    bar/iota
 
455
  ###    $ 
 
456
  ### 
 
457
  ### Commit the change from foo, then update bar.  The repository
 
458
  ### change should get folded into bar/iota with no conflict, since
 
459
  ### the two modifications are identical.
 
460
 
 
461
  sbox.build()
 
462
  wc_dir = sbox.wc_dir
 
463
 
 
464
  # Modify iota.
 
465
  iota_path = os.path.join(wc_dir, 'iota')
 
466
  svntest.main.file_append(iota_path, "\nA change to iota.\n")
 
467
 
 
468
  # Duplicate locally modified wc, giving us the "other" wc.
 
469
  other_wc = sbox.add_wc_path('other')
 
470
  svntest.actions.duplicate_dir(wc_dir, other_wc)
 
471
  other_iota_path = os.path.join(other_wc, 'iota')
 
472
 
 
473
  # Created expected output tree for 'svn ci'
 
474
  expected_output = svntest.wc.State(wc_dir, {
 
475
    'iota' : Item(verb='Sending'),
 
476
    })
 
477
 
 
478
  # Create expected status tree
 
479
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
480
  expected_status.tweak(wc_rev=1)
 
481
  expected_status.tweak('iota', wc_rev=2)
 
482
 
 
483
  # Commit the change, creating revision 2.
 
484
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
485
                                        expected_status, None,
 
486
                                        None, None, None, None, wc_dir)
 
487
 
 
488
  # Expected output tree for update of other_wc.
 
489
  expected_output = svntest.wc.State(other_wc, {
 
490
    'iota' : Item(status='G '),
 
491
    })
 
492
 
 
493
  # Expected disk tree for the update.
 
494
  expected_disk = svntest.main.greek_state.copy()
 
495
  expected_disk.tweak('iota',
 
496
                      contents="This is the file 'iota'.\nA change to iota.\n")
 
497
 
 
498
  # Expected status tree for the update.
 
499
  expected_status = svntest.actions.get_virginal_state(other_wc, 2)
 
500
  
 
501
  # Do the update and check the results in three ways.
 
502
  svntest.actions.run_and_verify_update(other_wc,
 
503
                                        expected_output,
 
504
                                        expected_disk,
 
505
                                        expected_status)
 
506
 
 
507
#----------------------------------------------------------------------
 
508
 
 
509
# Helper for update_to_resolve_text_conflicts() test -- a singleton handler.
 
510
def detect_conflict_files(node, extra_files):
 
511
  """NODE has been discovered an extra file on disk.  Verify that it
 
512
  matches one of the regular expressions in the EXTRA_FILES list.  If
 
513
  it matches, remove the match from the list.  If it doesn't match,
 
514
  raise an exception."""
 
515
 
 
516
  for pattern in extra_files:
 
517
    mo = re.match(pattern, node.name)
 
518
    if mo:
 
519
      extra_files.pop(extra_files.index(pattern)) # delete pattern from list
 
520
      break
 
521
  else:
 
522
    print "Found unexpected object:", node.name
 
523
    raise svntest.main.SVNTreeUnequal
 
524
 
 
525
def update_to_resolve_text_conflicts(sbox):
 
526
  "delete files and update to resolve text conflicts"
 
527
  
 
528
  sbox.build()
 
529
  wc_dir = sbox.wc_dir
 
530
 
 
531
  # Make a backup copy of the working copy
 
532
  wc_backup = sbox.add_wc_path('backup')
 
533
  svntest.actions.duplicate_dir(wc_dir, wc_backup)
 
534
 
 
535
  # Make a couple of local mods to files which will be committed
 
536
  mu_path = os.path.join(wc_dir, 'A', 'mu')
 
537
  rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
 
538
  svntest.main.file_append (mu_path, '\nOriginal appended text for mu')
 
539
  svntest.main.file_append (rho_path, '\nOriginal appended text for rho')
 
540
  svntest.main.run_svn (None, 'propset', 'Kubla', 'Khan', rho_path)
 
541
 
 
542
  # Make a couple of local mods to files which will be conflicted
 
543
  mu_path_backup = os.path.join(wc_backup, 'A', 'mu')
 
544
  rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho')
 
545
  svntest.main.file_append (mu_path_backup,
 
546
                             '\nConflicting appended text for mu')
 
547
  svntest.main.file_append (rho_path_backup,
 
548
                             '\nConflicting appended text for rho')
 
549
  svntest.main.run_svn (None, 'propset', 'Kubla', 'Xanadu', rho_path_backup)
 
550
 
 
551
  # Created expected output tree for 'svn ci'
 
552
  expected_output = svntest.wc.State(wc_dir, {
 
553
    'A/mu' : Item(verb='Sending'),
 
554
    'A/D/G/rho' : Item(verb='Sending'),
 
555
    })
 
556
 
 
557
  # Create expected status tree; all local revisions should be at 1,
 
558
  # but mu and rho should be at revision 2.
 
559
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
560
  expected_status.tweak(wc_rev=1)
 
561
  expected_status.tweak('A/mu', wc_rev=2)
 
562
  expected_status.tweak('A/D/G/rho', wc_rev=2, status='  ')
 
563
 
 
564
  # Commit.
 
565
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
566
                                        expected_status, None,
 
567
                                        None, None, None, None, wc_dir)
 
568
 
 
569
  # Create expected output tree for an update of the wc_backup.
 
570
  expected_output = svntest.wc.State(wc_backup, {
 
571
    'A/mu' : Item(status='C '),
 
572
    'A/D/G/rho' : Item(status='CC'),
 
573
    })
 
574
  
 
575
  # Create expected disk tree for the update.
 
576
  expected_disk = svntest.main.greek_state.copy()
 
577
  expected_disk.tweak('A/mu', contents= """<<<<<<< .mine
 
578
This is the file 'mu'.
 
579
Conflicting appended text for mu=======
 
580
This is the file 'mu'.
 
581
Original appended text for mu>>>>>>> .r2
 
582
""")
 
583
  expected_disk.tweak('A/D/G/rho', contents="""<<<<<<< .mine
 
584
This is the file 'rho'.
 
585
Conflicting appended text for rho=======
 
586
This is the file 'rho'.
 
587
Original appended text for rho>>>>>>> .r2
 
588
""")
 
589
 
 
590
  # Create expected status tree for the update.
 
591
  expected_status = svntest.actions.get_virginal_state(wc_backup, 2)
 
592
  expected_status.tweak('A/mu', status='C ')
 
593
  expected_status.tweak('A/D/G/rho', status='CC')
 
594
 
 
595
  # "Extra" files that we expect to result from the conflicts.
 
596
  # These are expressed as list of regexps.  What a cool system!  :-)
 
597
  extra_files = ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine',
 
598
                 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine', 'rho.*\.prej']
 
599
  
 
600
  # Do the update and check the results in three ways.
 
601
  # All "extra" files are passed to detect_conflict_files().
 
602
  svntest.actions.run_and_verify_update(wc_backup,
 
603
                                        expected_output,
 
604
                                        expected_disk,
 
605
                                        expected_status,
 
606
                                        None,
 
607
                                        detect_conflict_files,
 
608
                                        extra_files)
 
609
 
 
610
  
 
611
  # verify that the extra_files list is now empty.
 
612
  if len(extra_files) != 0:
 
613
    print "didn't get expected extra files"
 
614
    raise svntest.Failure
 
615
 
 
616
  # remove the conflicting files to clear text conflict but not props conflict
 
617
  os.remove(mu_path_backup)
 
618
  os.remove(rho_path_backup)
 
619
 
 
620
  # ### TODO: Can't get run_and_verify_update to work here :-( I get
 
621
  # the error "Unequal Types: one Node is a file, the other is a
 
622
  # directory". Use run_svn and then run_and_verify_status instead
 
623
  stdout_lines, stdout_lines = svntest.main.run_svn(None, 'up', wc_backup)  
 
624
  if len (stdout_lines) > 0:
 
625
    print "update 2 failed"
 
626
    raise svntest.Failure
 
627
 
 
628
  # Create expected status tree
 
629
  expected_status = svntest.actions.get_virginal_state(wc_backup, 2)
 
630
  expected_status.tweak('A/D/G/rho', status=' C')
 
631
 
 
632
  svntest.actions.run_and_verify_status(wc_backup, expected_status)
 
633
 
 
634
#----------------------------------------------------------------------
 
635
 
 
636
def update_delete_modified_files(sbox):
 
637
  "update that deletes modified files"
 
638
 
 
639
  sbox.build()
 
640
  wc_dir = sbox.wc_dir
 
641
 
 
642
  # Delete a file
 
643
  alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
 
644
  svntest.actions.run_and_verify_svn("Deleting alpha failed", None, [],
 
645
                                     'rm', alpha_path)
 
646
 
 
647
  # Delete a directory containing files
 
648
  G_path = os.path.join(wc_dir, 'A', 'D', 'G')
 
649
  svntest.actions.run_and_verify_svn("Deleting G failed", None, [],
 
650
                                     'rm', G_path)
 
651
 
 
652
  # Commit
 
653
  svntest.actions.run_and_verify_svn("Committing deletes failed", None, [],
 
654
                                     'ci', '-m', 'log msg', wc_dir)
 
655
 
 
656
  # ### Update before backdating to avoid obstructed update error for G
 
657
  svntest.actions.run_and_verify_svn("Updating after commit failed", None, [],
 
658
                                     'up', wc_dir)
 
659
 
 
660
  # Backdate to restore deleted items
 
661
  svntest.actions.run_and_verify_svn("Backdating failed", None, [],
 
662
                                     'up', '-r', '1', wc_dir)
 
663
 
 
664
  # Modify the file to be deleted, and a file in the directory to be deleted
 
665
  svntest.main.file_append(alpha_path, 'appended alpha text')
 
666
  pi_path = os.path.join(G_path, 'pi')
 
667
  svntest.main.file_append(pi_path, 'appended pi text')
 
668
 
 
669
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
 
670
  expected_status.tweak('A/B/E/alpha', 'A/D/G/pi', status='M ')
 
671
 
 
672
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
673
 
 
674
  # Now update to 'delete' modified files -- that is, remove them from
 
675
  # version control, but leave them on disk.  It used to be we would
 
676
  # expect an 'obstructed update' error (see issue #1196), but
 
677
  # nowadays we expect success (see issue #1806).
 
678
  expected_output = svntest.wc.State(wc_dir, {
 
679
    'A/B/E/alpha' : Item(status='D '),
 
680
    'A/D/G'       : Item(status='D '),
 
681
    })
 
682
  expected_disk = svntest.main.greek_state.copy()
 
683
  expected_disk.tweak('A/B/E/alpha',
 
684
                      contents="This is the file 'alpha'.appended alpha text")
 
685
  expected_disk.tweak('A/D/G/pi',
 
686
                      contents="This is the file 'pi'.appended pi text")
 
687
  expected_disk.remove('A/D/G/rho')
 
688
  expected_disk.remove('A/D/G/tau')
 
689
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
690
  expected_status.remove('A/B/E/alpha')
 
691
  expected_status.remove('A/D/G')
 
692
  expected_status.remove('A/D/G/pi')
 
693
  expected_status.remove('A/D/G/rho')
 
694
  expected_status.remove('A/D/G/tau')
 
695
  svntest.actions.run_and_verify_update(wc_dir,
 
696
                                        expected_output,
 
697
                                        expected_disk,
 
698
                                        expected_status)
 
699
 
 
700
 
 
701
#----------------------------------------------------------------------
 
702
 
 
703
# Issue 847.  Doing an add followed by a remove for an item in state
 
704
# "deleted" caused the "deleted" state to get forgotten
 
705
 
 
706
def update_after_add_rm_deleted(sbox):
 
707
  "update after add/rm of deleted state"
 
708
 
 
709
  sbox.build()
 
710
  wc_dir = sbox.wc_dir
 
711
 
 
712
  # Delete a file and directory from WC
 
713
  alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
 
714
  F_path = os.path.join(wc_dir, 'A', 'B', 'F')
 
715
  svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path, F_path)
 
716
 
 
717
  # Commit deletion
 
718
  expected_output = svntest.wc.State(wc_dir, {
 
719
    'A/B/E/alpha' : Item(verb='Deleting'),
 
720
    'A/B/F'       : Item(verb='Deleting'),
 
721
    })
 
722
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
723
  expected_status.tweak(wc_rev=1)
 
724
  expected_status.remove('A/B/E/alpha')
 
725
  expected_status.remove('A/B/F')
 
726
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
727
                                        expected_status, None,
 
728
                                        None, None, None, None, wc_dir)
 
729
 
 
730
  # alpha and F are now in state "deleted", next we add a new ones
 
731
  svntest.main.file_append(alpha_path, "new alpha")
 
732
  svntest.actions.run_and_verify_svn(None, None, [], 'add', alpha_path)
 
733
 
 
734
  svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', F_path)
 
735
 
 
736
  # New alpha and F should be in add state A
 
737
  expected_status.add({
 
738
    'A/B/E/alpha' : Item(status='A ', wc_rev=0),
 
739
    'A/B/F'       : Item(status='A ', wc_rev=0),
 
740
    })
 
741
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
742
  
 
743
  # Forced removal of new alpha and F must restore "deleted" state
 
744
  
 
745
  svntest.actions.run_and_verify_svn(None, None, [], 'rm', '--force',
 
746
                                     alpha_path, F_path)
 
747
  if os.path.exists(alpha_path) or os.path.exists(F_path):
 
748
    raise svntest.Failure
 
749
 
 
750
  # "deleted" state is not visible in status
 
751
  expected_status.remove('A/B/E/alpha', 'A/B/F')
 
752
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
753
 
 
754
  # Although parent dir is already at rev 1, the "deleted" state will cause
 
755
  # alpha and F to be restored in the WC when updated to rev 1
 
756
  svntest.actions.run_and_verify_svn(None, None, [], 'up', '-r', '1', wc_dir)
 
757
  expected_status.add({
 
758
    'A/B/E/alpha' : Item(status='  ', wc_rev=1),
 
759
    'A/B/F'       : Item(status='  ', wc_rev=1),
 
760
    })
 
761
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
762
 
 
763
#----------------------------------------------------------------------
 
764
 
 
765
# Issue 1591.  Updating a working copy which contains local
 
766
# obstructions marks a directory as incomplete.  Removal of the
 
767
# obstruction and subsequent update should clear the "incomplete"
 
768
# flag.
 
769
 
 
770
def obstructed_update_alters_wc_props(sbox):
 
771
  "obstructed update alters WC properties"
 
772
 
 
773
  sbox.build()
 
774
  wc_dir = sbox.wc_dir
 
775
 
 
776
  # Create a new dir in the repo in prep for creating an obstruction.
 
777
  #print "Adding dir to repo"
 
778
  svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', '-m',
 
779
                                     'prep for obstruction',
 
780
                                     sbox.repo_url + '/A/foo')
 
781
 
 
782
  # Create an obstruction, a file in the WC with the same name as
 
783
  # present in a newer rev of the repo.
 
784
  #print "Creating obstruction"
 
785
  obstruction_parent_path = os.path.join(wc_dir, 'A')
 
786
  obstruction_path = os.path.join(obstruction_parent_path, 'foo')
 
787
  svntest.main.file_append(obstruction_path, 'an obstruction')
 
788
 
 
789
  # Update the WC to that newer rev to trigger the obstruction.
 
790
  #print "Updating WC"
 
791
  expected_output = svntest.wc.State(wc_dir, {})
 
792
  expected_disk = svntest.main.greek_state.copy()
 
793
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
 
794
  error_re = 'Failed to add directory.*object of the same name already exists'
 
795
  svntest.actions.run_and_verify_update(wc_dir,
 
796
                                        expected_output,
 
797
                                        expected_disk,
 
798
                                        expected_status,
 
799
                                        error_re)
 
800
 
 
801
  # Remove the file which caused the obstruction.
 
802
  #print "Removing obstruction"
 
803
  os.unlink(obstruction_path)
 
804
 
 
805
  # Update the -- now unobstructed -- WC again.
 
806
  #print "Updating WC again"
 
807
  expected_output = svntest.wc.State(wc_dir, {
 
808
    'A/foo' : Item(status='A '),
 
809
    })
 
810
  expected_disk = svntest.main.greek_state.copy()
 
811
  expected_disk.add({
 
812
    'A/foo' : Item(),
 
813
    })
 
814
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
815
  expected_status.add({
 
816
    'A/foo' : Item(status='  ', wc_rev=2),
 
817
    })
 
818
  svntest.actions.run_and_verify_update(wc_dir,
 
819
                                        expected_output,
 
820
                                        expected_disk,
 
821
                                        expected_status)
 
822
 
 
823
  # The previously obstructed resource should now be in the WC.
 
824
  if not os.path.isdir(obstruction_path):
 
825
    raise svntest.Failure
 
826
 
 
827
#----------------------------------------------------------------------
 
828
 
 
829
# Issue 938.
 
830
def update_replace_dir(sbox):
 
831
  "update that replaces a directory"
 
832
 
 
833
  sbox.build()
 
834
  wc_dir = sbox.wc_dir
 
835
 
 
836
  # Delete a directory
 
837
  F_path = os.path.join(wc_dir, 'A', 'B', 'F')
 
838
  svntest.actions.run_and_verify_svn(None, None, [], 'rm', F_path)
 
839
 
 
840
  # Commit deletion
 
841
  expected_output = svntest.wc.State(wc_dir, {
 
842
    'A/B/F'       : Item(verb='Deleting'),
 
843
    })
 
844
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
845
  expected_status.tweak(wc_rev=1)
 
846
  expected_status.remove('A/B/F')
 
847
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
848
                                        expected_status, None,
 
849
                                        None, None, None, None, wc_dir)
 
850
 
 
851
  # Add replacement directory
 
852
  svntest.actions.run_and_verify_svn(None, None, [], 'mkdir', F_path)
 
853
 
 
854
  # Commit addition
 
855
  expected_output = svntest.wc.State(wc_dir, {
 
856
    'A/B/F'       : Item(verb='Adding'),
 
857
    })
 
858
  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
 
859
  expected_status.tweak(wc_rev=1)
 
860
  expected_status.tweak('A/B/F', wc_rev=3)
 
861
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
862
                                        expected_status, None,
 
863
                                        None, None, None, None, wc_dir)
 
864
 
 
865
  # Update to HEAD
 
866
  expected_output = svntest.wc.State(wc_dir, {
 
867
    })
 
868
  expected_disk = svntest.main.greek_state.copy()
 
869
  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
 
870
  svntest.actions.run_and_verify_update(wc_dir,
 
871
                                        expected_output,
 
872
                                        expected_disk,
 
873
                                        expected_status)
 
874
 
 
875
  # Update to revision 1 replaces the directory
 
876
  ### I can't get this to work :-(
 
877
  #expected_output = svntest.wc.State(wc_dir, {
 
878
  #  'A/B/F'       : Item(verb='Adding'),
 
879
  #  'A/B/F'       : Item(verb='Deleting'),
 
880
  #  })
 
881
  #expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
 
882
  #svntest.actions.run_and_verify_update(wc_dir,
 
883
  #                                      expected_output,
 
884
  #                                      expected_disk,
 
885
  #                                      expected_status,
 
886
  #                                      None, None, None, None, None, 0,
 
887
  #                                      '-r', '1', wc_dir)
 
888
 
 
889
  # Update to revision 1 replaces the directory
 
890
  svntest.actions.run_and_verify_svn(None, None, [], 'up', '-r', '1', wc_dir)
 
891
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
 
892
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
893
 
 
894
#----------------------------------------------------------------------
 
895
 
 
896
def update_single_file(sbox):
 
897
  "update with explicit file target"
 
898
  
 
899
  sbox.build()
 
900
  wc_dir = sbox.wc_dir
 
901
 
 
902
  expected_disk = svntest.main.greek_state.copy()
 
903
 
 
904
  # Make a local mod to a file which will be committed
 
905
  mu_path = os.path.join(wc_dir, 'A', 'mu')
 
906
  svntest.main.file_append (mu_path, '\nAppended text for mu')
 
907
 
 
908
  # Commit.
 
909
  expected_output = svntest.wc.State(wc_dir, {
 
910
    'A/mu' : Item(verb='Sending'),
 
911
    })
 
912
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
913
  expected_status.tweak(wc_rev=1)
 
914
  expected_status.tweak('A/mu', wc_rev=2)
 
915
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
916
                                        expected_status, None,
 
917
                                        None, None, None, None, wc_dir)
 
918
 
 
919
  # At one stage 'svn up file' failed with a parent lock error
 
920
  was_cwd = os.getcwd()
 
921
  os.chdir(os.path.join(wc_dir, 'A'))
 
922
 
 
923
  try:
 
924
    ### Can't get run_and_verify_update to work having done the chdir.
 
925
    svntest.actions.run_and_verify_svn("update failed", None, [],
 
926
                                       'up', '-r', '1', 'mu')
 
927
  finally:
 
928
    os.chdir(was_cwd)
 
929
 
 
930
  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
 
931
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
932
 
 
933
#----------------------------------------------------------------------
 
934
def prop_update_on_scheduled_delete(sbox):
 
935
  "receive prop update to file scheduled for deletion"
 
936
  
 
937
  sbox.build()
 
938
  wc_dir = sbox.wc_dir
 
939
  
 
940
  other_wc = sbox.add_wc_path('other')
 
941
 
 
942
  # Make the "other" working copy.
 
943
  svntest.actions.duplicate_dir(wc_dir, other_wc)
 
944
 
 
945
  iota_path = os.path.join(wc_dir, 'iota')
 
946
  other_iota_path = os.path.join(other_wc, 'iota')
 
947
 
 
948
  svntest.main.run_svn (None, 'propset', 'foo', 'bar', iota_path)
 
949
 
 
950
  # Created expected output tree for 'svn ci'
 
951
  expected_output = svntest.wc.State(wc_dir, {
 
952
    'iota' : Item(verb='Sending'),
 
953
    })
 
954
 
 
955
  # Create expected status tree
 
956
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
957
  expected_status.tweak(wc_rev=1)
 
958
  expected_status.tweak('iota', wc_rev=2)
 
959
 
 
960
  # Commit the change, creating revision 2.
 
961
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
962
                                        expected_status, None,
 
963
                                        None, None, None, None, wc_dir)
 
964
 
 
965
  svntest.main.run_svn (None, 'rm', other_iota_path)
 
966
 
 
967
  # Expected output tree for update of other_wc.
 
968
  expected_output = svntest.wc.State(other_wc, {
 
969
    'iota' : Item(status=' U'),
 
970
    })
 
971
 
 
972
  # Expected disk tree for the update.
 
973
  expected_disk = svntest.main.greek_state.copy()
 
974
  expected_disk.remove('iota')
 
975
 
 
976
  # Expected status tree for the update.
 
977
  expected_status = svntest.actions.get_virginal_state(other_wc, 2)
 
978
  expected_status.tweak('iota', status='D ')
 
979
  
 
980
  # Do the update and check the results in three ways.
 
981
  svntest.actions.run_and_verify_update(other_wc,
 
982
                                        expected_output,
 
983
                                        expected_disk,
 
984
                                        expected_status)
 
985
 
 
986
#----------------------------------------------------------------------
 
987
 
 
988
def update_receive_illegal_name(sbox):
 
989
  "bail when receive a file or dir named .svn"
 
990
 
 
991
  sbox.build()
 
992
  wc_dir = sbox.wc_dir
 
993
 
 
994
  # This tests the revision 4334 fix for issue #1068.
 
995
  
 
996
  legal_url = svntest.main.current_repo_url + '/A/D/G/svn'
 
997
  illegal_url = svntest.main.current_repo_url + '/A/D/G/.svn'
 
998
  # Ha!  The client doesn't allow us to mkdir a '.svn' but it does
 
999
  # allow us to copy to a '.svn' so ...
 
1000
  svntest.actions.run_and_verify_svn(None, None, [],
 
1001
                                     'mkdir', '-m', 'log msg',
 
1002
                                     legal_url)
 
1003
  svntest.actions.run_and_verify_svn(None, None, [],
 
1004
                                     'mv', '-m', 'log msg',
 
1005
                                     legal_url, illegal_url)
 
1006
 
 
1007
  # Do the update twice, both should fail.  After the first failure
 
1008
  # the wc will be marked "incomplete".
 
1009
  for n in range(2):
 
1010
    out, err = svntest.main.run_svn(1, 'up', wc_dir)
 
1011
    for line in err:
 
1012
      if line.find("object of the same name already exists") != -1:
 
1013
        break
 
1014
    else:
 
1015
      raise svntest.Failure
 
1016
 
 
1017
  # At one stage an obstructed update in an incomplete wc would leave
 
1018
  # a txn behind
 
1019
  out, err = svntest.main.run_svnadmin('lstxns', sbox.repo_dir)
 
1020
  if out or err:
 
1021
    raise svntest.Failure
 
1022
 
 
1023
#----------------------------------------------------------------------
 
1024
 
 
1025
def update_deleted_missing_dir(sbox):
 
1026
  "update missing dir to rev in which it is absent"
 
1027
 
 
1028
  sbox.build()
 
1029
  wc_dir = sbox.wc_dir
 
1030
  
 
1031
  E_path = os.path.join(wc_dir, 'A', 'B', 'E')
 
1032
  H_path = os.path.join(wc_dir, 'A', 'D', 'H')
 
1033
 
 
1034
  # Create a new revision with directories deleted
 
1035
  svntest.main.run_svn(None, 'rm', E_path)  
 
1036
  svntest.main.run_svn(None, 'rm', H_path)  
 
1037
  svntest.main.run_svn(None, 'ci', '-m', 'log msg', E_path, H_path)  
 
1038
 
 
1039
  # Update back to the old revision
 
1040
  svntest.main.run_svn(None, 'up', '-r', '1', wc_dir)  
 
1041
 
 
1042
  # Delete the directories from disk
 
1043
  svntest.main.safe_rmtree(E_path)
 
1044
  svntest.main.safe_rmtree(H_path)
 
1045
 
 
1046
  # Create expected output tree for an update of the missing items by name
 
1047
  expected_output = svntest.wc.State(wc_dir, {
 
1048
    'A/B/E' : Item(status='D '),
 
1049
    'A/D/H' : Item(status='D '),
 
1050
    })
 
1051
 
 
1052
  # Create expected disk tree for the update.
 
1053
  expected_disk = svntest.main.greek_state.copy()
 
1054
  expected_disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
 
1055
  expected_disk.remove('A/D/H', 'A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi')
 
1056
 
 
1057
  # Create expected status tree for the update.
 
1058
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1059
  expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
 
1060
  expected_status.remove('A/D/H', 'A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi')
 
1061
  expected_status.tweak(wc_rev=1)
 
1062
 
 
1063
  # Do the update, specifying the deleted paths explicitly. 
 
1064
  svntest.actions.run_and_verify_update(wc_dir,
 
1065
                                        expected_output,
 
1066
                                        expected_disk,
 
1067
                                        expected_status,
 
1068
                                        None, None, None, None, None, 
 
1069
                                        0, "-r", "2", E_path, H_path)
 
1070
 
 
1071
  # Update back to the old revision again
 
1072
  svntest.main.run_svn(None, 'up', '-r', '1', wc_dir)  
 
1073
 
 
1074
  # Delete the directories from disk
 
1075
  svntest.main.safe_rmtree(E_path)
 
1076
  svntest.main.safe_rmtree(H_path)
 
1077
 
 
1078
  # This time we're updating the whole working copy
 
1079
  expected_status.tweak(wc_rev=2)
 
1080
 
 
1081
  # Do the update, on the whole working copy this time
 
1082
  svntest.actions.run_and_verify_update(wc_dir,
 
1083
                                        expected_output,
 
1084
                                        expected_disk,
 
1085
                                        expected_status,
 
1086
                                        None, None, None, None, None, 
 
1087
                                        0, "-r", "2", wc_dir)
 
1088
 
 
1089
#----------------------------------------------------------------------
 
1090
 
 
1091
# Issue 919.  This test was written as a regression test for "item
 
1092
# should remain 'deleted' when an update deletes a sibling".
 
1093
def another_hudson_problem(sbox):
 
1094
  "another \"hudson\" problem: updates that delete"
 
1095
 
 
1096
  sbox.build()
 
1097
  wc_dir = sbox.wc_dir
 
1098
 
 
1099
  # Delete/commit gamma thus making it 'deleted'
 
1100
  gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma') 
 
1101
  svntest.main.run_svn(None, 'rm', gamma_path)
 
1102
  expected_output = svntest.wc.State(wc_dir, {
 
1103
    'A/D/gamma' : Item(verb='Deleting'),
 
1104
    })
 
1105
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1106
  expected_status.tweak(wc_rev=1)
 
1107
  expected_status.remove('A/D/gamma')
 
1108
  svntest.actions.run_and_verify_commit (wc_dir,
 
1109
                                         expected_output,
 
1110
                                         expected_status,
 
1111
                                         None, None, None, None, None,
 
1112
                                         wc_dir)
 
1113
 
 
1114
  # Delete directory G from the repository
 
1115
  svntest.actions.run_and_verify_svn(None,
 
1116
                                     ['\n', 'Committed revision 3.\n'], None,
 
1117
                                     'rm', '-m', 'log msg',
 
1118
                                     svntest.main.current_repo_url + '/A/D/G')
 
1119
 
 
1120
  # Remove corresponding tree from working copy
 
1121
  G_path = os.path.join(wc_dir, 'A', 'D', 'G')
 
1122
  svntest.main.safe_rmtree(G_path)
 
1123
 
 
1124
  # Update missing directory to receive the delete, this should mark G
 
1125
  # as 'deleted' and should not alter gamma's entry.
 
1126
 
 
1127
  # Sigh, I can't get run_and_verify_update to work (but not because
 
1128
  # of issue 919 as far as I can tell)
 
1129
  svntest.actions.run_and_verify_svn(None,
 
1130
                                     ['D    '+G_path+'\n',
 
1131
                                      'Updated to revision 3.\n'], None,
 
1132
                                     'up', G_path)
 
1133
 
 
1134
  # Both G and gamma should be 'deleted', update should produce no output
 
1135
  expected_output = svntest.wc.State(wc_dir, { })
 
1136
  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
 
1137
  expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
 
1138
                         'A/D/gamma')
 
1139
  expected_disk = svntest.main.greek_state.copy()
 
1140
  expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau',
 
1141
                       'A/D/gamma')
 
1142
  svntest.actions.run_and_verify_update(wc_dir,
 
1143
                                        expected_output,
 
1144
                                        expected_disk,
 
1145
                                        expected_status)  
 
1146
 
 
1147
#----------------------------------------------------------------------
 
1148
def update_deleted_targets(sbox):
 
1149
  "explicit update of deleted=true targets"
 
1150
 
 
1151
  sbox.build()
 
1152
  wc_dir = sbox.wc_dir
 
1153
 
 
1154
  # Delete/commit thus creating 'deleted=true' entries
 
1155
  gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma') 
 
1156
  F_path = os.path.join(wc_dir, 'A', 'B', 'F')
 
1157
  svntest.main.run_svn(None, 'rm', gamma_path, F_path)
 
1158
  expected_output = svntest.wc.State(wc_dir, {
 
1159
    'A/D/gamma' : Item(verb='Deleting'),
 
1160
    'A/B/F'     : Item(verb='Deleting'),
 
1161
    })
 
1162
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1163
  expected_status.tweak(wc_rev=1)
 
1164
  expected_status.remove('A/D/gamma', 'A/B/F')
 
1165
  svntest.actions.run_and_verify_commit (wc_dir,
 
1166
                                         expected_output,
 
1167
                                         expected_status,
 
1168
                                         None, None, None, None, None,
 
1169
                                         wc_dir)
 
1170
 
 
1171
  # Explicit update must not remove the 'deleted=true' entries
 
1172
  svntest.actions.run_and_verify_svn(None, ['At revision 2.\n'], None,
 
1173
                                     'update', gamma_path)
 
1174
  svntest.actions.run_and_verify_svn(None, ['At revision 2.\n'], None,
 
1175
                                     'update', F_path)
 
1176
 
 
1177
  # Update to r1 to restore items, since the parent directory is already
 
1178
  # at r1 this fails if the 'deleted=true' entries are missing (issue 2250)
 
1179
  expected_output = svntest.wc.State(wc_dir, {
 
1180
    'A/D/gamma' : Item(status='A '),
 
1181
    'A/B/F'     : Item(status='A '),
 
1182
    })
 
1183
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1184
  expected_disk = svntest.main.greek_state.copy()
 
1185
  expected_status.tweak(wc_rev=1)
 
1186
  svntest.actions.run_and_verify_update(wc_dir,
 
1187
                                        expected_output,
 
1188
                                        expected_disk,
 
1189
                                        expected_status,  
 
1190
                                        None, None, None, None, None, 0,
 
1191
                                        '-r', '1', wc_dir)
 
1192
  
 
1193
 
 
1194
 
 
1195
#----------------------------------------------------------------------
 
1196
 
 
1197
def new_dir_with_spaces(sbox):
 
1198
  "receive new dir with spaces in its name"
 
1199
 
 
1200
  sbox.build()
 
1201
  wc_dir = sbox.wc_dir
 
1202
 
 
1203
  # Create a new directory ("spacey dir") directly in repository
 
1204
  svntest.actions.run_and_verify_svn(None,
 
1205
                                     ['\n', 'Committed revision 2.\n'], None,
 
1206
                                     'mkdir', '-m', 'log msg',
 
1207
                                     svntest.main.current_repo_url
 
1208
                                     + '/A/spacey%20dir')
 
1209
 
 
1210
  # Update, and make sure ra_dav doesn't choke on the space.
 
1211
  expected_output = svntest.wc.State(wc_dir, {
 
1212
    'A/spacey dir'       : Item(status='A '),
 
1213
    })
 
1214
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1215
  expected_status.add({
 
1216
    'A/spacey dir'       : Item(status='  ', wc_rev=2),
 
1217
    })
 
1218
  expected_disk = svntest.main.greek_state.copy()
 
1219
  expected_disk.add({
 
1220
    'A/spacey dir' : Item(),
 
1221
    })
 
1222
 
 
1223
  svntest.actions.run_and_verify_update(wc_dir,
 
1224
                                        expected_output,
 
1225
                                        expected_disk,
 
1226
                                        expected_status)  
 
1227
 
 
1228
#----------------------------------------------------------------------
 
1229
 
 
1230
def non_recursive_update(sbox):
 
1231
  "non-recursive update"
 
1232
 
 
1233
  sbox.build()
 
1234
  wc_dir = sbox.wc_dir
 
1235
 
 
1236
  # Commit a change to A/mu and A/D/G/rho
 
1237
  mu_path = os.path.join(wc_dir, 'A', 'mu')
 
1238
  rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
 
1239
  svntest.main.file_append(mu_path, "new")
 
1240
  svntest.main.file_append(rho_path, "new")
 
1241
  expected_output = svntest.wc.State(wc_dir, {
 
1242
    'A/mu' : Item(verb='Sending'),
 
1243
    'A/D/G/rho' : Item(verb='Sending'),
 
1244
    })
 
1245
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1246
  expected_status.tweak(wc_rev=1)
 
1247
  expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2)
 
1248
  svntest.actions.run_and_verify_commit (wc_dir, expected_output,
 
1249
                                         expected_status,
 
1250
                                         None, None, None, None, None,
 
1251
                                         wc_dir)
 
1252
 
 
1253
  # Update back to revision 1
 
1254
  expected_output = svntest.wc.State(wc_dir, {
 
1255
    'A/mu' : Item(status='U '),
 
1256
    'A/D/G/rho' : Item(status='U '),
 
1257
    })
 
1258
  expected_disk = svntest.main.greek_state.copy()
 
1259
  expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=1)
 
1260
  svntest.actions.run_and_verify_update(wc_dir, expected_output,
 
1261
                                        expected_disk, expected_status,
 
1262
                                        None, None, None, None, None, 0,
 
1263
                                        '-r', '1', wc_dir)
 
1264
 
 
1265
  # Non-recursive update of A should change A/mu but not A/D/G/rho
 
1266
  A_path = os.path.join(wc_dir, 'A')
 
1267
  expected_output = svntest.wc.State(wc_dir, {
 
1268
    'A/mu' : Item(status='U '),
 
1269
    })
 
1270
  expected_status.tweak('A', 'A/mu', wc_rev=2)
 
1271
  expected_disk.tweak('A/mu', contents="This is the file 'mu'.new")
 
1272
  svntest.actions.run_and_verify_update(wc_dir, expected_output,
 
1273
                                        expected_disk, expected_status,
 
1274
                                        None, None, None, None, None, 0,
 
1275
                                        '-N', A_path)
 
1276
 
 
1277
#----------------------------------------------------------------------
 
1278
 
 
1279
def checkout_empty_dir(sbox):
 
1280
  "check out an empty dir"
 
1281
  # See issue #1472 -- checked out empty dir should not be marked as
 
1282
  # incomplete ("!" in status).
 
1283
  sbox.build()
 
1284
  wc_dir = sbox.wc_dir
 
1285
  
 
1286
  C_url = svntest.main.current_repo_url + '/A/C'
 
1287
 
 
1288
  svntest.main.safe_rmtree(wc_dir)
 
1289
  svntest.actions.run_and_verify_svn(None, None, [], 'checkout', C_url, wc_dir)
 
1290
 
 
1291
  svntest.actions.run_and_verify_svn(None, [], [], 'status', wc_dir)
 
1292
 
 
1293
 
 
1294
#----------------------------------------------------------------------
 
1295
# Regression test for issue #919: "another ghudson bug".  Basically, if
 
1296
# we fore- or back-date an item until it no longer exists, we were
 
1297
# completely removing the entry, rather than marking it 'deleted'
 
1298
# (which we now do.)
 
1299
 
 
1300
def update_to_deletion(sbox):
 
1301
  "update target till it's gone, then get it back"
 
1302
 
 
1303
  sbox.build()
 
1304
  wc_dir = sbox.wc_dir
 
1305
 
 
1306
  iota_path = os.path.join(wc_dir, 'iota')
 
1307
 
 
1308
  # Update iota to rev 0, so it gets removed.
 
1309
  expected_output = svntest.wc.State(wc_dir, {
 
1310
    'iota' : Item(status='D '),
 
1311
    })
 
1312
  expected_disk = svntest.main.greek_state.copy()
 
1313
  expected_disk.remove('iota')
 
1314
 
 
1315
  svntest.actions.run_and_verify_update(wc_dir,
 
1316
                                        expected_output,
 
1317
                                        expected_disk,
 
1318
                                        None, None,
 
1319
                                        None, None, None, None, 0,
 
1320
                                        '-r', '0', iota_path)
 
1321
 
 
1322
  # Update the wc root, so iota comes back.
 
1323
  expected_output = svntest.wc.State(wc_dir, {
 
1324
    'iota' : Item(status='A '),
 
1325
    })
 
1326
  expected_disk = svntest.main.greek_state.copy()
 
1327
 
 
1328
  svntest.actions.run_and_verify_update(wc_dir,
 
1329
                                        expected_output,
 
1330
                                        expected_disk,
 
1331
                                        None, None,
 
1332
                                        None, None, None, None, 0,
 
1333
                                        wc_dir)
 
1334
  
 
1335
 
 
1336
#----------------------------------------------------------------------
 
1337
 
 
1338
def update_deletion_inside_out(sbox):
 
1339
  "update child before parent of a deleted tree"
 
1340
 
 
1341
  sbox.build()
 
1342
  wc_dir = sbox.wc_dir
 
1343
 
 
1344
  parent_path = os.path.join(wc_dir, 'A', 'B')
 
1345
  child_path = os.path.join(parent_path, 'E')  # Could be a file, doesn't matter
 
1346
 
 
1347
  # Delete the parent directory.
 
1348
  svntest.actions.run_and_verify_svn(None, None, [],
 
1349
                                     'rm', parent_path)
 
1350
  svntest.actions.run_and_verify_svn(None, None, [],
 
1351
                                     'ci', '-m', '', wc_dir)
 
1352
 
 
1353
  # Update back to r1.
 
1354
  svntest.actions.run_and_verify_svn(None, None, [],
 
1355
                                     'update', '-r', '1', wc_dir)
 
1356
 
 
1357
  # Update just the child to r2.
 
1358
  svntest.actions.run_and_verify_svn(None, None, [],
 
1359
                                     'update', '-r', '2', child_path)
 
1360
 
 
1361
  # Now try a normal update.
 
1362
  expected_output = svntest.wc.State(wc_dir, {
 
1363
    'A/B' : Item(status='D '),
 
1364
    })
 
1365
  expected_disk = svntest.main.greek_state.copy()
 
1366
  expected_disk.remove('A/B', 'A/B/lambda', 'A/B/F',
 
1367
                       'A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
 
1368
 
 
1369
  svntest.actions.run_and_verify_update(wc_dir,
 
1370
                                        expected_output,
 
1371
                                        expected_disk,
 
1372
                                        None)
 
1373
 
 
1374
 
 
1375
#----------------------------------------------------------------------
 
1376
# Regression test for issue #1793, whereby 'svn up dir' would delete
 
1377
# dir if schedule-add.  Yikes.
 
1378
 
 
1379
def update_schedule_add_dir(sbox):
 
1380
  "update a schedule-add directory"
 
1381
 
 
1382
  sbox.build()
 
1383
  wc_dir = sbox.wc_dir
 
1384
 
 
1385
  # Delete directory A/D/G in the repository via immediate commit
 
1386
  G_path = os.path.join(wc_dir, 'A', 'D', 'G')
 
1387
  G_url = svntest.main.current_repo_url + '/A/D/G'
 
1388
  svntest.actions.run_and_verify_svn(None, None, [],
 
1389
                                     'rm', G_url, '-m', 'rev 2')
 
1390
 
 
1391
  # Update the wc to HEAD (r2)
 
1392
  expected_output = svntest.wc.State(wc_dir, {
 
1393
    'A/D/G' : Item(status='D '),
 
1394
    })
 
1395
  expected_disk = svntest.main.greek_state.copy()
 
1396
  expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
 
1397
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1398
  expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau')
 
1399
  svntest.actions.run_and_verify_update(wc_dir,
 
1400
                                        expected_output,
 
1401
                                        expected_disk,
 
1402
                                        expected_status)
 
1403
 
 
1404
  # Do a URL->wc copy, creating a new schedule-add A/D/G.
 
1405
  # (Standard procedure when trying to resurrect the directory.)
 
1406
  D_path = os.path.join(wc_dir, 'A', 'D')
 
1407
  svntest.actions.run_and_verify_svn("Copy error:", None, [],
 
1408
                                     'cp', '-r', '1', G_url, D_path)
 
1409
 
 
1410
  # status should now show the dir scheduled for addition-with-history
 
1411
  expected_status.add({
 
1412
    'A/D/G'     : Item(status='A ', copied='+', wc_rev='-'),
 
1413
    'A/D/G/pi'  : Item(status='  ', copied='+', wc_rev='-'),
 
1414
    'A/D/G/rho' : Item(status='  ', copied='+', wc_rev='-'),
 
1415
    'A/D/G/tau' : Item(status='  ', copied='+', wc_rev='-'),
 
1416
    })
 
1417
  svntest.actions.run_and_verify_status (wc_dir, expected_status)
 
1418
 
 
1419
  # Now update with the schedule-add dir as the target.
 
1420
  svntest.actions.run_and_verify_svn(None, None, [], 'up', G_path)
 
1421
 
 
1422
  # The update should be a no-op, and the schedule-add directory
 
1423
  # should still exist!  'svn status' shouldn't change at all.
 
1424
  svntest.actions.run_and_verify_status (wc_dir, expected_status)
 
1425
  
 
1426
 
 
1427
#----------------------------------------------------------------------
 
1428
# Test updating items that do not exist in the current WC rev, but do
 
1429
# exist at some future revision.
 
1430
 
 
1431
def update_to_future_add(sbox):
 
1432
  "update target that was added in a future rev"
 
1433
 
 
1434
  sbox.build()
 
1435
  wc_dir = sbox.wc_dir
 
1436
  
 
1437
  # Update the entire WC to rev 0
 
1438
  # Create expected output tree for an update to rev 0
 
1439
  expected_output = svntest.wc.State(wc_dir, {
 
1440
    'iota' : Item(status='D '),
 
1441
    'A' : Item(status='D '),
 
1442
    })
 
1443
 
 
1444
  # Create expected disk tree for the update to rev 0
 
1445
  expected_disk = svntest.wc.State(wc_dir, { })
 
1446
  
 
1447
  # Do the update and check the results.
 
1448
  svntest.actions.run_and_verify_update(wc_dir,
 
1449
                                        expected_output,
 
1450
                                        expected_disk,
 
1451
                                        None, None,
 
1452
                                        None, None, None, None, 0,
 
1453
                                        '-r', '0', wc_dir)
 
1454
 
 
1455
  # Update iota to the current HEAD.
 
1456
  iota_path = os.path.join(wc_dir, 'iota')
 
1457
  expected_output = svntest.wc.State(wc_dir, {
 
1458
    'iota' : Item(status='A '),
 
1459
    })
 
1460
  expected_disk = svntest.wc.State('', {
 
1461
   'iota' : Item("This is the file 'iota'.")
 
1462
   })
 
1463
 
 
1464
  svntest.actions.run_and_verify_update(wc_dir,
 
1465
                                        expected_output,
 
1466
                                        expected_disk,
 
1467
                                        None, None,
 
1468
                                        None, None, None, None, 0,
 
1469
                                        iota_path)
 
1470
 
 
1471
  # Now try updating the directory into the future
 
1472
  A_path = os.path.join(wc_dir, 'A')
 
1473
 
 
1474
  expected_status = svntest.wc.State(wc_dir, {
 
1475
    'A'              : Item(status='A '),
 
1476
    'A/mu'           : Item(status='A '),
 
1477
    'A/B'            : Item(status='A '),
 
1478
    'A/B/lambda'     : Item(status='A '),
 
1479
    'A/B/E'          : Item(status='A '),
 
1480
    'A/B/E/alpha'    : Item(status='A '),
 
1481
    'A/B/E/beta'     : Item(status='A '),
 
1482
    'A/B/F'          : Item(status='A '),
 
1483
    'A/C'            : Item(status='A '),
 
1484
    'A/D'            : Item(status='A '),
 
1485
    'A/D/gamma'      : Item(status='A '),
 
1486
    'A/D/G'          : Item(status='A '),
 
1487
    'A/D/G/pi'       : Item(status='A '),
 
1488
    'A/D/G/rho'      : Item(status='A '),
 
1489
    'A/D/G/tau'      : Item(status='A '),
 
1490
    'A/D/H'          : Item(status='A '),
 
1491
    'A/D/H/chi'      : Item(status='A '),
 
1492
    'A/D/H/psi'      : Item(status='A '),
 
1493
    'A/D/H/omega'    : Item(status='A ')
 
1494
    })
 
1495
  expected_disk = svntest.main.greek_state.copy()
 
1496
  
 
1497
  svntest.actions.run_and_verify_update(wc_dir,
 
1498
                                        expected_status,
 
1499
                                        expected_disk,
 
1500
                                        None, None,
 
1501
                                        None, None, None, None, 0,
 
1502
                                        A_path);
 
1503
 
 
1504
#----------------------------------------------------------------------
 
1505
 
 
1506
def nested_in_read_only(sbox):
 
1507
  "update a nested wc in a read-only wc"
 
1508
 
 
1509
  sbox.build()
 
1510
  wc_dir = sbox.wc_dir
 
1511
 
 
1512
  # Delete/commit a file
 
1513
  alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
 
1514
  svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
 
1515
  expected_output = svntest.wc.State(wc_dir, {
 
1516
    'A/B/E/alpha' : Item(verb='Deleting'),
 
1517
    })
 
1518
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1519
  expected_status.tweak(wc_rev=1)
 
1520
  expected_status.remove('A/B/E/alpha')
 
1521
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
1522
                                        expected_status, None,
 
1523
                                        None, None, None, None, wc_dir)
 
1524
  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
 
1525
  expected_status.tweak(wc_rev=2)
 
1526
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
1527
 
 
1528
  # Delete/commit a directory that used to contain the deleted file
 
1529
  B_path = os.path.join(wc_dir, 'A', 'B')      
 
1530
  svntest.actions.run_and_verify_svn(None, None, [], 'rm', B_path)
 
1531
  expected_output = svntest.wc.State(wc_dir, {
 
1532
    'A/B' : Item(verb='Deleting'),
 
1533
    })
 
1534
  expected_status.remove('A/B', 'A/B/lambda', 'A/B/E', 'A/B/E/beta', 'A/B/F')
 
1535
  svntest.actions.run_and_verify_commit(wc_dir, expected_output,
 
1536
                                        expected_status, None,
 
1537
                                        None, None, None, None, wc_dir)
 
1538
 
 
1539
  svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
 
1540
  expected_status.tweak(wc_rev=3)
 
1541
  svntest.actions.run_and_verify_status(wc_dir, expected_status)
 
1542
 
 
1543
  # Replace the deleted directory with a new checkout of an old
 
1544
  # version of the directory, this gives it a "plausible" URL that
 
1545
  # could be part of the containing wc
 
1546
  B_url = svntest.main.current_repo_url + '/A/B'
 
1547
  svntest.actions.run_and_verify_svn(None, None, [],
 
1548
                                     'checkout', '-r', '1', B_url + "@1",
 
1549
                                     B_path)
 
1550
  expected_status = svntest.wc.State(B_path, {
 
1551
    ''           : Item(),
 
1552
    'lambda'     : Item(),
 
1553
    'E'          : Item(),
 
1554
    'E/alpha'    : Item(),
 
1555
    'E/beta'     : Item(),
 
1556
    'F'          : Item(),
 
1557
    })
 
1558
  expected_status.tweak(wc_rev=1, status='  ')
 
1559
  svntest.actions.run_and_verify_status(B_path, expected_status)
 
1560
 
 
1561
  # Make enclosing wc read only
 
1562
  os.chmod(os.path.join(wc_dir, 'A', svntest.main.get_admin_name()), 0555)
 
1563
  
 
1564
  try:
 
1565
    # Update of nested wc should still work
 
1566
    expected_output = svntest.wc.State(B_path, {
 
1567
      'E/alpha' : Item(status='D '),
 
1568
      })
 
1569
    expected_disk = wc.State('', {
 
1570
      'lambda'  : wc.StateItem("This is the file 'lambda'."),
 
1571
      'E'       : wc.StateItem(),
 
1572
      'E/beta'  : wc.StateItem("This is the file 'beta'."),
 
1573
      'F'       : wc.StateItem(),
 
1574
      })
 
1575
    expected_status.remove('E/alpha')
 
1576
    expected_status.tweak(wc_rev=2)
 
1577
    svntest.actions.run_and_verify_update(B_path,
 
1578
                                          expected_output,
 
1579
                                          expected_disk,
 
1580
                                          expected_status,
 
1581
                                          None, None, None, None, None, 0,
 
1582
                                          '-r', '2', B_path)
 
1583
  finally:
 
1584
    os.chmod(os.path.join(wc_dir, 'A', svntest.main.get_admin_name()), 0777)
 
1585
 
 
1586
#----------------------------------------------------------------------
 
1587
 
 
1588
def update_xml_unsafe_dir(sbox):
 
1589
  "update dir with xml-unsafe name"
 
1590
 
 
1591
  sbox.build()
 
1592
  wc_dir = sbox.wc_dir
 
1593
 
 
1594
  # Make a backup copy of the working copy
 
1595
  wc_backup = sbox.add_wc_path('backup')
 
1596
  svntest.actions.duplicate_dir(wc_dir, wc_backup)
 
1597
 
 
1598
  # Make a couple of local mods to files
 
1599
  test_path = os.path.join(wc_dir, ' foo & bar')
 
1600
  svntest.main.run_svn(None, 'mkdir', test_path)  
 
1601
 
 
1602
  # Created expected output tree for 'svn ci'
 
1603
  expected_output = wc.State(wc_dir, {
 
1604
    ' foo & bar' : Item(verb='Adding'),
 
1605
    })
 
1606
 
 
1607
  # Create expected status tree; all local revisions should be at 1,
 
1608
  # but 'foo & bar' should be at revision 2.
 
1609
  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
 
1610
  expected_status.tweak(wc_rev=1)
 
1611
  expected_status.add({
 
1612
    ' foo & bar' : Item(status='  ', wc_rev=2),
 
1613
    })
 
1614
 
 
1615
  # Commit.
 
1616
  svntest.actions.run_and_verify_commit (wc_dir, expected_output,
 
1617
                                         expected_status, None,
 
1618
                                         None, None, None, None, wc_dir)
 
1619
 
 
1620
  # chdir into the funky path, and update from there.
 
1621
  was_cwd = os.getcwd()
 
1622
  os.chdir(test_path)
 
1623
  try:
 
1624
    svntest.actions.run_and_verify_svn("Update failed", None, [], 'up')
 
1625
  finally:
 
1626
    os.chdir(was_cwd)
 
1627
 
 
1628
########################################################################
 
1629
# Run the tests
 
1630
 
 
1631
 
 
1632
# list all tests here, starting with None:
 
1633
test_list = [ None,
 
1634
              update_binary_file,
 
1635
              update_binary_file_2,
 
1636
              update_ignores_added,
 
1637
              update_to_rev_zero,
 
1638
              receive_overlapping_same_change,
 
1639
              update_to_resolve_text_conflicts,
 
1640
              update_delete_modified_files,
 
1641
              update_after_add_rm_deleted,
 
1642
              update_missing,
 
1643
              update_replace_dir,
 
1644
              update_single_file,
 
1645
              prop_update_on_scheduled_delete,
 
1646
              update_receive_illegal_name,
 
1647
              update_deleted_missing_dir,
 
1648
              another_hudson_problem,
 
1649
              update_deleted_targets,
 
1650
              new_dir_with_spaces,
 
1651
              non_recursive_update,
 
1652
              checkout_empty_dir,
 
1653
              update_to_deletion,
 
1654
              update_deletion_inside_out,
 
1655
              update_schedule_add_dir,
 
1656
              update_to_future_add,
 
1657
              nested_in_read_only,
 
1658
              obstructed_update_alters_wc_props,
 
1659
              update_xml_unsafe_dir,
 
1660
             ]
 
1661
 
 
1662
if __name__ == '__main__':
 
1663
  svntest.main.run_tests(test_list)
 
1664
  # NOTREACHED
 
1665
 
 
1666
 
 
1667
### End of file.