1#!/usr/bin/env python 2# 3# prop_tests.py: testing versioned properties 4# 5# Subversion is a tool for revision control. 6# See http://subversion.apache.org for more information. 7# 8# ==================================================================== 9# Licensed to the Apache Software Foundation (ASF) under one 10# or more contributor license agreements. See the NOTICE file 11# distributed with this work for additional information 12# regarding copyright ownership. The ASF licenses this file 13# to you under the Apache License, Version 2.0 (the 14# "License"); you may not use this file except in compliance 15# with the License. You may obtain a copy of the License at 16# 17# http://www.apache.org/licenses/LICENSE-2.0 18# 19# Unless required by applicable law or agreed to in writing, 20# software distributed under the License is distributed on an 21# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22# KIND, either express or implied. See the License for the 23# specific language governing permissions and limitations 24# under the License. 25###################################################################### 26 27# General modules 28import sys, re, os, stat, subprocess, logging 29 30logger = logging.getLogger() 31 32# Our testing module 33import svntest 34 35from svntest.main import SVN_PROP_MERGEINFO 36from svntest.main import SVN_PROP_INHERITABLE_IGNORES 37from svntest import wc 38 39# (abbreviation) 40Skip = svntest.testcase.Skip_deco 41SkipUnless = svntest.testcase.SkipUnless_deco 42XFail = svntest.testcase.XFail_deco 43Issues = svntest.testcase.Issues_deco 44Issue = svntest.testcase.Issue_deco 45Wimp = svntest.testcase.Wimp_deco 46Item = svntest.wc.StateItem 47 48def is_non_posix_and_non_windows_os(): 49 """lambda function to skip revprop_change test""" 50 return (not svntest.main.is_posix_os()) and sys.platform != 'win32' 51 52# this is global so other test files can use it 53binary_mime_type_on_text_file_warning = \ 54 "svn: warning:.*is a binary mime-type but file.*looks like text.*" 55 56###################################################################### 57# Tests 58 59#---------------------------------------------------------------------- 60 61def make_local_props(sbox): 62 "write/read props in wc only (ps, pl, pdel, pe)" 63 64 # Bootstrap 65 sbox.build() 66 wc_dir = sbox.wc_dir 67 68 # Add properties to one file and one directory 69 sbox.simple_propset('blue', 'azul', 'A/mu') 70 sbox.simple_propset('green', 'verde', 'A/mu') 71 sbox.simple_propset('editme', 'the foo fighters', 'A/mu') 72 sbox.simple_propset('red', 'rojo', 'A/D/G') 73 sbox.simple_propset('yellow', 'amarillo', 'A/D/G') 74 75 # Make sure they show up as local mods in status 76 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 77 expected_status.tweak('A/mu', status=' M') 78 expected_status.tweak('A/D/G', status=' M') 79 80 svntest.actions.run_and_verify_status(wc_dir, expected_status) 81 82 # Remove one property 83 sbox.simple_propdel('yellow', 'A/D/G') 84 85 svntest.main.use_editor('foo_to_bar') 86 # Edit one property 87 svntest.main.run_svn(None, 'propedit', 'editme', 88 os.path.join(wc_dir, 'A', 'mu')) 89 90 # What we expect the disk tree to look like: 91 expected_disk = svntest.main.greek_state.copy() 92 expected_disk.tweak('A/mu', props={'blue' : 'azul', 'green' : 'verde', 93 'editme' : 'the bar fighters'}) 94 expected_disk.tweak('A/D/G', props={'red' : 'rojo'}) 95 96 # Read the real disk tree. Notice we are passing the (normally 97 # disabled) "load props" flag to this routine. This will run 'svn 98 # proplist' on every item in the working copy! 99 svntest.actions.verify_disk(wc_dir, expected_disk, True) 100 101 # Edit without actually changing the property 102 svntest.main.use_editor('identity') 103 svntest.actions.run_and_verify_svn("No changes to property 'editme' on '.*'", 104 [], 105 'propedit', 'editme', 106 os.path.join(wc_dir, 'A', 'mu')) 107 108 109 110#---------------------------------------------------------------------- 111 112def commit_props(sbox): 113 "commit properties" 114 115 # Bootstrap 116 sbox.build() 117 wc_dir = sbox.wc_dir 118 119 # Add a property to a file and a directory 120 sbox.simple_propset('blue', 'azul', 'A/mu') 121 sbox.simple_propset('red', 'rojo', 'A/D/H') 122 123 # Create expected output tree. 124 expected_output = svntest.wc.State(wc_dir, { 125 'A/mu' : Item(verb='Sending'), 126 'A/D/H' : Item(verb='Sending'), 127 }) 128 129 # Created expected status tree. 130 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 131 expected_status.tweak('A/mu', 'A/D/H', wc_rev=2, status=' ') 132 133 # Commit the one file. 134 svntest.actions.run_and_verify_commit(wc_dir, 135 expected_output, 136 expected_status) 137 138 139 140#---------------------------------------------------------------------- 141 142@Issue(3951) 143def update_props(sbox): 144 "receive properties via update" 145 146 # Bootstrap 147 sbox.build() 148 wc_dir = sbox.wc_dir 149 150 # Make a backup copy of the working copy 151 wc_backup = sbox.add_wc_path('backup') 152 svntest.actions.duplicate_dir(wc_dir, wc_backup) 153 154 # Add a property to a file and a directory 155 sbox.simple_propset('blue', 'azul', 'A/mu') 156 sbox.simple_propset('red', 'rojo', 'A/D/H') 157 158 # Create expected output tree. 159 expected_output = svntest.wc.State(wc_dir, { 160 'A/mu' : Item(verb='Sending'), 161 'A/D/H' : Item(verb='Sending'), 162 }) 163 164 # Created expected status tree. 165 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 166 expected_status.tweak('A/mu', 'A/D/H', wc_rev=2, status=' ') 167 168 # Commit property mods 169 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 170 expected_status) 171 172 # Add more properties 173 sbox.simple_propset('blue2', 'azul2', 'A/mu') 174 sbox.simple_propset('red2', 'rojo2', 'A/D/H') 175 expected_status.tweak('A/mu', 'A/D/H', wc_rev=3, status=' ') 176 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 177 expected_status) 178 179 # Create expected output tree for an update of the wc_backup. 180 expected_output = svntest.wc.State(wc_backup, { 181 'A/mu' : Item(status=' U'), 182 'A/D/H' : Item(status=' U'), 183 }) 184 185 # Create expected disk tree for the update. 186 expected_disk = svntest.main.greek_state.copy() 187 expected_disk.tweak('A/mu', props={'blue' : 'azul'}) 188 expected_disk.tweak('A/D/H', props={'red' : 'rojo'}) 189 190 # Create expected status tree for the update. 191 expected_status = svntest.actions.get_virginal_state(wc_backup, 2) 192 expected_status.tweak('A/mu', 'A/D/H', status=' ') 193 194 # Do the update and check the results in three ways... INCLUDING PROPS 195 # This adds properties to nodes that have none 196 svntest.actions.run_and_verify_update(wc_backup, 197 expected_output, 198 expected_disk, 199 expected_status, 200 [], 1, 201 '-r', '2', wc_backup) 202 203 # This adds properties to nodes that have properties 204 expected_status.tweak(wc_rev=3) 205 expected_disk.tweak('A/mu', props={'blue' : 'azul', 206 'blue2' : 'azul2'}) 207 expected_disk.tweak('A/D/H', props={'red' : 'rojo', 208 'red2' : 'rojo2'}) 209 svntest.actions.run_and_verify_update(wc_backup, 210 expected_output, 211 expected_disk, 212 expected_status, 213 [], 1, 214 '-r', '3', wc_backup) 215 216 217#---------------------------------------------------------------------- 218 219def downdate_props(sbox): 220 "receive property changes as part of a downdate" 221 222 # Bootstrap 223 sbox.build() 224 wc_dir = sbox.wc_dir 225 226 mu_path = sbox.ospath('A/mu') 227 228 # Add a property to a file 229 sbox.simple_propset('cash-sound', 'cha-ching!', 'iota') 230 231 # Create expected output tree. 232 expected_output = svntest.wc.State(wc_dir, { 233 'iota' : Item(verb='Sending'), 234 }) 235 236 # Created expected status tree. 237 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 238 expected_status.tweak('iota', wc_rev=2, status=' ') 239 240 # Commit the one file. 241 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 242 expected_status) 243 244 # Make some mod (something to commit) 245 svntest.main.file_append(mu_path, "some mod") 246 247 # Create expected output tree. 248 expected_output = svntest.wc.State(wc_dir, { 249 'A/mu' : Item(verb='Sending'), 250 }) 251 252 # Created expected status tree. 253 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 254 expected_status.tweak('iota', wc_rev=2, status=' ') 255 expected_status.tweak('A/mu', wc_rev=3, status=' ') 256 257 # Commit the one file. 258 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 259 expected_status) 260 261 # Create expected output tree for an update. 262 expected_output = svntest.wc.State(wc_dir, { 263 'iota' : Item(status=' U'), 264 'A/mu' : Item(status='U '), 265 }) 266 267 # Create expected disk tree for the update. 268 expected_disk = svntest.main.greek_state 269 270 # Create expected status tree for the update. 271 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 272 273 # Do the update and check the results in three ways... INCLUDING PROPS 274 svntest.actions.run_and_verify_update(wc_dir, 275 expected_output, 276 expected_disk, 277 expected_status, 278 [], 1, 279 '-r', '1', wc_dir) 280 281#---------------------------------------------------------------------- 282 283def remove_props(sbox): 284 "commit the removal of props" 285 286 # Bootstrap 287 sbox.build() 288 wc_dir = sbox.wc_dir 289 290 # Add a property to a file 291 sbox.simple_propset('cash-sound', 'cha-ching!', 'iota') 292 293 # Commit the file 294 sbox.simple_commit('iota') 295 296 # Now, remove the property 297 sbox.simple_propdel('cash-sound', 'iota') 298 299 # Create expected output tree. 300 expected_output = svntest.wc.State(wc_dir, { 301 'iota' : Item(verb='Sending'), 302 }) 303 304 # Created expected status tree. 305 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 306 expected_status.tweak('iota', wc_rev=3, status=' ') 307 308 # Commit the one file. 309 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 310 expected_status) 311 312#---------------------------------------------------------------------- 313 314def update_conflict_props(sbox): 315 "update with conflicting props" 316 317 # Bootstrap 318 sbox.build() 319 wc_dir = sbox.wc_dir 320 321 # Add a property to a file and a directory 322 mu_path = sbox.ospath('A/mu') 323 sbox.simple_propset('cash-sound', 'cha-ching!', 'A/mu') 324 A_path = sbox.ospath('A') 325 sbox.simple_propset('foo', 'bar', 'A') 326 327 # Commit the file and directory 328 sbox.simple_commit() 329 330 # Update to rev 1 331 svntest.main.run_svn(None, 'up', '-r', '1', wc_dir) 332 333 # Add conflicting properties 334 sbox.simple_propset('cash-sound', 'beep!', 'A/mu') 335 sbox.simple_propset('foo', 'baz', 'A') 336 337 # Create expected output tree for an update of the wc_backup. 338 expected_output = svntest.wc.State(wc_dir, { 339 'A/mu' : Item(status=' C'), 340 'A' : Item(status=' C'), 341 }) 342 343 # Create expected disk tree for the update. 344 expected_disk = svntest.main.greek_state.copy() 345 expected_disk.tweak('A/mu', props={'cash-sound' : 'beep!'}) 346 expected_disk.tweak('A', props={'foo' : 'baz'}) 347 348 # Create expected status tree for the update. 349 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 350 expected_status.tweak('A/mu', 'A', status=' C') 351 352 extra_files = ['mu.*\.prej', 'dir_conflicts.*\.prej'] 353 # Do the update and check the results in three ways... INCLUDING PROPS 354 svntest.actions.run_and_verify_update(wc_dir, 355 expected_output, 356 expected_disk, 357 expected_status, 358 check_props=True, 359 extra_files=extra_files) 360 361 # Resolve the conflicts 362 svntest.actions.run_and_verify_resolved([mu_path, A_path]) 363 364 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 365 expected_status.tweak('A/mu', 'A', status=' M') 366 367 svntest.actions.run_and_verify_status(wc_dir, expected_status) 368 369#---------------------------------------------------------------------- 370@Issue(2608) 371def commit_conflict_dirprops(sbox): 372 "commit with conflicting dirprops" 373 374 # Issue #2608: failure to see conflicting dirprops on root of 375 # repository. 376 377 # Bootstrap 378 sbox.build() 379 wc_dir = sbox.wc_dir 380 381 sbox.simple_propset('foo', 'bar', '') 382 383 # Commit the file and directory 384 sbox.simple_commit() 385 386 # Update to rev 1 387 svntest.main.run_svn(None, 388 'up', '-r', '1', wc_dir) 389 390 # Add conflicting properties 391 sbox.simple_propset('foo', 'eek', '') 392 393 svntest.actions.run_and_verify_commit(wc_dir, None, None, 394 ".*[oO]ut[- ]of[- ]date.*") 395 396#---------------------------------------------------------------------- 397 398# Issue #742: we used to screw up when committing a file replacement 399# that also had properties. It was fixed by teaching 400# svn_wc_props_modified_p and svn_wc_transmit_prop_deltas to *ignore* 401# leftover base-props when a file is scheduled for replacement. (When 402# we svn_wc_add a file, it starts life with no working props.) 403@Issue(742) 404def commit_replacement_props(sbox): 405 "props work when committing a replacement" 406 407 # Bootstrap 408 sbox.build() 409 wc_dir = sbox.wc_dir 410 411 # Add a property to two files 412 iota_path = sbox.ospath('iota') 413 lambda_path = sbox.ospath('A/B/lambda') 414 sbox.simple_propset('cash-sound', 'cha-ching!', 'iota') 415 sbox.simple_propset('boson', 'W', 'A/B/lambda') 416 417 # Commit (### someday use run_and_verify_commit for better coverage) 418 sbox.simple_commit() 419 420 # Schedule both files for deletion 421 sbox.simple_rm('iota', 'A/B/lambda') 422 423 # Now recreate the files, and schedule them for addition. 424 # Poof, the 'new' files don't have any properties at birth. 425 svntest.main.file_append(iota_path, 'iota TNG') 426 svntest.main.file_append(lambda_path, 'lambda TNG') 427 sbox.simple_add('iota', 'A/B/lambda') 428 429 # Sanity check: the two files should be scheduled for (R)eplacement. 430 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 431 expected_status.tweak('iota', wc_rev=2, status='R ') 432 expected_status.tweak('A/B/lambda', wc_rev=2, status='R ') 433 434 svntest.actions.run_and_verify_status(wc_dir, expected_status) 435 436 # Now add a property to lambda. Iota still doesn't have any. 437 sbox.simple_propset('capacitor', 'flux', 'A/B/lambda') 438 439 # Commit, with careful output checking. We're actually going to 440 # scan the working copy for props after the commit. 441 442 expected_output = svntest.wc.State(wc_dir, { 443 'iota' : Item(verb='Replacing'), 444 'A/B/lambda' : Item(verb='Replacing'), 445 }) 446 447 # Expected status tree: lambda has one prop, iota doesn't. 448 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 449 expected_status.tweak('iota', wc_rev=3) 450 expected_status.tweak('A/B/lambda', wc_rev=3, status=' ') 451 452 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 453 expected_status) 454 455#---------------------------------------------------------------------- 456 457def revert_replacement_props(sbox): 458 "props work when reverting a replacement" 459 460 # Bootstrap 461 sbox.build() 462 wc_dir = sbox.wc_dir 463 464 # Add a property to two files 465 iota_path = sbox.ospath('iota') 466 lambda_path = sbox.ospath('A/B/lambda') 467 sbox.simple_propset('cash-sound', 'cha-ching!', 'iota') 468 sbox.simple_propset('boson', 'W', 'A/B/lambda') 469 470 # Commit rev 2. (### someday use run_and_verify_commit for better coverage) 471 sbox.simple_commit() 472 473 # Schedule both files for deletion 474 sbox.simple_rm('iota', 'A/B/lambda') 475 476 # Now recreate the files, and schedule them for addition. 477 # Poof, the 'new' files don't have any properties at birth. 478 svntest.main.file_append(iota_path, 'iota TNG') 479 svntest.main.file_append(lambda_path, 'lambda TNG') 480 sbox.simple_add('iota', 'A/B/lambda') 481 482 # Sanity check: the two files should be scheduled for (R)eplacement. 483 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 484 expected_status.tweak('iota', wc_rev=2, status='R ') 485 expected_status.tweak('A/B/lambda', wc_rev=2, status='R ') 486 487 svntest.actions.run_and_verify_status(wc_dir, expected_status) 488 489 # Now add a property to lambda. Iota still doesn't have any. 490 sbox.simple_propset('capacitor', 'flux', 'A/B/lambda') 491 492 # Now revert both files. 493 sbox.simple_revert('iota', 'A/B/lambda') 494 495 # Do an update; even though the update is really a no-op, 496 # run_and_verify_update has the nice feature of scanning disk as 497 # well as running status. We want to verify that we truly have a 498 # *pristine* revision 2 tree, with the original rev 2 props, and no 499 # local mods at all. 500 501 expected_output = svntest.wc.State(wc_dir, { 502 }) 503 504 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 505 expected_status.tweak('iota', status=' ') 506 expected_status.tweak('A/B/lambda', status=' ') 507 508 expected_disk = svntest.main.greek_state.copy() 509 expected_disk.tweak('iota', props={'cash-sound' : 'cha-ching!'}) 510 expected_disk.tweak('A/B/lambda', props={'boson' : 'W'}) 511 512 # scan disk for props too. 513 svntest.actions.run_and_verify_update(wc_dir, 514 expected_output, 515 expected_disk, 516 expected_status, 517 check_props=True) 518 519#---------------------------------------------------------------------- 520@Issues(920,2065) 521def inappropriate_props(sbox): 522 "try to set inappropriate props" 523 524 # Bootstrap 525 sbox.build() 526 wc_dir = sbox.wc_dir 527 528 A_path = sbox.ospath('A') 529 E_path = sbox.ospath('A/B/E') 530 iota_path = sbox.ospath('iota') 531 532 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 533 svntest.actions.run_and_verify_status(wc_dir, expected_status) 534 535 # These should produce an error 536 svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, 537 'propset', 'svn:executable', 'on', A_path) 538 539 svntest.actions.run_and_verify_svn(None, 540 svntest.verify.AnyOutput, 'propset', 541 'svn:keywords', 'LastChangedDate', 542 A_path) 543 544 svntest.actions.run_and_verify_svn(None, 545 svntest.verify.AnyOutput, 'propset', 546 'svn:eol-style', 'native', A_path) 547 548 svntest.actions.run_and_verify_svn(None, 549 svntest.verify.AnyOutput, 'propset', 550 'svn:eol-style', 'invalid value', 551 os.path.join(A_path, 'mu')) 552 553 svntest.actions.run_and_verify_svn(None, 554 svntest.verify.AnyOutput, 'propset', 555 'svn:mime-type', 'image/png', A_path) 556 557 svntest.actions.run_and_verify_svn(None, 558 svntest.verify.AnyOutput, 'propset', 559 'svn:ignore', '*.o', iota_path) 560 561 svntest.actions.run_and_verify_svn(None, 562 svntest.verify.AnyOutput, 'propset', 563 'svn:externals', 564 'foo http://host.com/repos', iota_path) 565 566 svntest.actions.run_and_verify_svn(None, 567 svntest.verify.AnyOutput, 'propset', 568 'svn:author', 'socrates', iota_path) 569 570 svntest.actions.run_and_verify_svn(None, 571 svntest.verify.AnyOutput, 'propset', 572 'svn:log', 'log message', iota_path) 573 574 svntest.actions.run_and_verify_svn(None, 575 svntest.verify.AnyOutput, 'propset', 576 'svn:date', 'Tue Jan 19 04:14:07 2038', 577 iota_path) 578 579 svntest.actions.run_and_verify_svn(None, 580 svntest.verify.AnyOutput, 'propset', 581 'svn:original-date', 582 'Thu Jan 1 01:00:00 1970', iota_path) 583 584 # Status unchanged 585 svntest.actions.run_and_verify_status(wc_dir, expected_status) 586 587 # Recursive setting of inappropriate dir prop should work on files 588 svntest.actions.run_and_verify_svn(None, [], 'propset', '-R', 589 'svn:executable', 'on', E_path) 590 591 expected_status.tweak('A/B/E/alpha', 'A/B/E/beta', status=' M') 592 svntest.actions.run_and_verify_status(wc_dir, expected_status) 593 594 # Issue #920. Don't allow setting of svn:eol-style on binary files or files 595 # with inconsistent eol types. 596 597 path = sbox.ospath('binary') 598 svntest.main.file_append(path, "binary") 599 sbox.simple_add('binary') 600 601 svntest.main.run_svn(binary_mime_type_on_text_file_warning, 602 'propset', 'svn:mime-type', 'application/octet-stream', 603 sbox.ospath('binary')) 604 605 svntest.actions.run_and_verify_svn(None, 606 svntest.verify.AnyOutput, 607 'propset', 'svn:eol-style', 608 'CRLF', path) 609 610 path = sbox.ospath('multi-eol') 611 svntest.main.file_append(path, "line1\rline2\n") 612 sbox.simple_add('multi-eol') 613 614 svntest.actions.run_and_verify_svn(None, 615 svntest.verify.AnyOutput, 616 'propset', 'svn:eol-style', 617 'LF', path) 618 619 path = sbox.ospath('backwards-eol') 620 svntest.main.file_append(path, "line1\n\r") 621 sbox.simple_add('backwards-eol') 622 623 svntest.actions.run_and_verify_svn(None, 624 svntest.verify.AnyOutput, 625 'propset', 'svn:eol-style', 626 'native', path) 627 628 path = sbox.ospath('incomplete-eol') 629 svntest.main.file_append(path, "line1\r\n\r") 630 sbox.simple_add('incomplete-eol') 631 632 svntest.actions.run_and_verify_svn(None, 633 svntest.verify.AnyOutput, 634 'propset', 'svn:eol-style', 635 'CR', path) 636 637 # Issue #2065. Do allow setting of svn:eol-style on binary files or files 638 # with inconsistent eol types if --force is passed. 639 640 path = sbox.ospath('binary') 641 svntest.main.file_append(path, "binary") 642 svntest.actions.run_and_verify_svn(None, [], 643 'propset', '--force', 644 'svn:eol-style', 'CRLF', 645 path) 646 647 path = sbox.ospath('multi-eol') 648 svntest.actions.run_and_verify_svn(None, [], 649 'propset', '--force', 650 'svn:eol-style', 'LF', 651 path) 652 653 path = sbox.ospath('backwards-eol') 654 svntest.actions.run_and_verify_svn(None, [], 655 'propset', '--force', 656 'svn:eol-style', 'native', 657 path) 658 659 path = sbox.ospath('incomplete-eol') 660 svntest.actions.run_and_verify_svn(None, [], 661 'propset', '--force', 662 'svn:eol-style', 'CR', 663 path) 664 665 # Prevent setting of svn:mergeinfo prop values that are... 666 path = sbox.ospath('A/D') 667 668 # ...grammatically incorrect 669 svntest.actions.run_and_verify_svn(None, 670 "svn: E200020: Pathname not terminated by ':'\n", 671 'propset', SVN_PROP_MERGEINFO, '/trunk', 672 path) 673 svntest.actions.run_and_verify_svn(None, 674 "svn: E200022: Invalid revision number found " 675 "parsing 'one'\n", 676 'propset', SVN_PROP_MERGEINFO, 677 '/trunk:one', path) 678 679 # ...contain overlapping revision ranges of differing inheritability. 680 svntest.actions.run_and_verify_svn(None, 681 "svn: E200020: Unable to parse overlapping " 682 "revision ranges '9-20\\*' and " 683 "'18-22' with different " 684 "inheritance types\n", 685 'propset', SVN_PROP_MERGEINFO, 686 '/branch:5-7,9-20*,18-22', path) 687 688 svntest.actions.run_and_verify_svn(None, 689 "svn: E200020: Unable to parse overlapping " 690 "revision ranges " 691 "(('3' and '3\\*')|('3\\*' and '3')) " 692 "with different " 693 "inheritance types\n", 694 'propset', SVN_PROP_MERGEINFO, 695 '/branch:3,3*', path) 696 697 # ...contain revision ranges with start revisions greater than or 698 # equal to end revisions. 699 svntest.actions.run_and_verify_svn(None, 700 "svn: E200020: Unable to parse reversed " 701 "revision range '20-5'\n", 702 'propset', SVN_PROP_MERGEINFO, 703 '/featureX:4,20-5', path) 704 705 # ...contain paths mapped to empty revision ranges 706 svntest.actions.run_and_verify_svn(None, 707 "svn: E200020: Mergeinfo for '/trunk' maps to " 708 "an empty revision range\n", 709 'propset', SVN_PROP_MERGEINFO, 710 '/trunk:', path) 711 712 # ...contain non-inheritable ranges when the target is a file. 713 svntest.actions.run_and_verify_svn(None, 714 "svn: E200020: Cannot set non-inheritable " 715 "mergeinfo on a non-directory*", 716 'propset', SVN_PROP_MERGEINFO, 717 '/A/D/H/psi:1*', iota_path) 718 719#---------------------------------------------------------------------- 720 721# Issue #976. When copying a file, do not determine svn:executable 722# and svn:mime-type values as though the file is brand new, instead 723# use the copied file's property values. 724@Issue(976) 725def copy_inherits_special_props(sbox): 726 "file copies inherit (not re-derive) special props" 727 728 # Bootstrap 729 sbox.build() 730 wc_dir = sbox.wc_dir 731 732 orig_mime_type = 'image/fake_image' 733 734 # Create two paths 735 new_path1 = sbox.ospath('new_file1.bin') 736 new_path2 = sbox.ospath('new_file2.bin') 737 738 # Create the first path as a binary file. To have svn treat the 739 # file as binary, have a 0x00 in the file. 740 svntest.main.file_append(new_path1, "binary file\000") 741 sbox.simple_add('new_file1.bin') 742 743 # Add initial svn:mime-type to the file 744 sbox.simple_propset('svn:mime-type', orig_mime_type, 'new_file1.bin') 745 746 # Set the svn:executable property on the file if this is a system 747 # that can handle chmod, in which case svn will turn on the 748 # executable bits on the file. Then remove the executable bits 749 # manually on the file and see the value of svn:executable in the 750 # copied file. 751 if os.name == 'posix': 752 sbox.simple_propset('svn:executable', 'on', 'new_file1.bin') 753 os.chmod(new_path1, svntest.main.S_ALL_READ | stat.S_IWUSR) 754 755 # Commit the file 756 sbox.simple_commit() 757 758 # Copy the file 759 svntest.main.run_svn(None, 'cp', new_path1, new_path2) 760 761 # Check the svn:mime-type 762 actual_exit, actual_stdout, actual_stderr = svntest.main.run_svn( 763 None, 'pg', 'svn:mime-type', new_path2) 764 765 expected_stdout = [orig_mime_type + '\n'] 766 if actual_stdout != expected_stdout: 767 logger.warn("svn pg svn:mime-type output does not match expected.") 768 logger.warn("Expected standard output: %s\n", expected_stdout) 769 logger.warn("Actual standard output: %s\n", actual_stdout) 770 raise svntest.verify.SVNUnexpectedOutput 771 772 # Check the svn:executable value. 773 # The value of the svn:executable property is now always forced to '*' 774 if os.name == 'posix': 775 actual_exit, actual_stdout, actual_stderr = svntest.main.run_svn( 776 None, 'pg', 'svn:executable', new_path2) 777 778 expected_stdout = ['*\n'] 779 if actual_stdout != expected_stdout: 780 logger.warn("svn pg svn:executable output does not match expected.") 781 logger.warn("Expected standard output: %s\n", expected_stdout) 782 logger.warn("Actual standard output: %s\n", actual_stdout) 783 raise svntest.verify.SVNUnexpectedOutput 784 785#---------------------------------------------------------------------- 786# Test for issue #3086 'mod-dav-svn ignores pre-revprop-change failure 787# on revprop delete' 788# 789# If we learn how to write a pre-revprop-change hook for 790# non-Posix platforms, we won't have to skip here: 791@Skip(is_non_posix_and_non_windows_os) 792@Issue(3086) 793def revprop_change(sbox): 794 "set, get, and delete a revprop change" 795 796 sbox.build() 797 798 # First test the error when no revprop-change hook exists. 799 svntest.actions.run_and_verify_svn(None, '.*pre-revprop-change', 800 'propset', '--revprop', '-r', '0', 801 'cash-sound', 'cha-ching!', sbox.wc_dir) 802 803 # Now test error output from revprop-change hook. 804 svntest.actions.disable_revprop_changes(sbox.repo_dir) 805 svntest.actions.run_and_verify_svn(None, '.*pre-revprop-change.* 0 jrandom cash-sound A', 806 'propset', '--revprop', '-r', '0', 807 'cash-sound', 'cha-ching!', sbox.wc_dir) 808 809 # Create the revprop-change hook for this test 810 svntest.actions.enable_revprop_changes(sbox.repo_dir) 811 812 svntest.actions.run_and_verify_svn(None, [], 813 'propset', '--revprop', '-r', '0', 814 'cash-sound', 'cha-ching!', sbox.wc_dir) 815 816 svntest.actions.run_and_verify_svn(None, [], 817 'propget', '--revprop', '-r', '0', 818 'cash-sound', sbox.wc_dir) 819 820 # Now test that blocking the revprop delete. 821 svntest.actions.disable_revprop_changes(sbox.repo_dir) 822 svntest.actions.run_and_verify_svn(None, '.*pre-revprop-change.* 0 jrandom cash-sound D', 823 'propdel', '--revprop', '-r', '0', 824 'cash-sound', sbox.wc_dir) 825 826 # Now test actually deleting the revprop. 827 svntest.actions.enable_revprop_changes(sbox.repo_dir) 828 svntest.actions.run_and_verify_svn(None, [], 829 'propdel', '--revprop', '-r', '0', 830 'cash-sound', sbox.wc_dir) 831 832 # The property should have been deleted. 833 svntest.actions.run_and_verify_svn(None, 834 '.*(E195011|E200017).*cash-sound.*', 835 'propget', '--revprop', '-r', '0', 'cash-sound', sbox.wc_dir) 836 837 838#---------------------------------------------------------------------- 839 840def prop_value_conversions(sbox): 841 "some svn: properties should be converted" 842 843 # Bootstrap 844 sbox.build() 845 wc_dir = sbox.wc_dir 846 847 A_path = sbox.ospath('A') 848 B_path = sbox.ospath('A/B') 849 iota_path = sbox.ospath('iota') 850 lambda_path = sbox.ospath('A/B/lambda') 851 mu_path = sbox.ospath('A/mu') 852 853 # Leading and trailing whitespace should be stripped 854 svntest.actions.set_prop('svn:mime-type', ' text/html\n\n', iota_path) 855 svntest.actions.set_prop('svn:mime-type', 'text/html', mu_path) 856 857 # Leading and trailing whitespace should be stripped 858 svntest.actions.set_prop('svn:eol-style', '\nnative\n', iota_path) 859 svntest.actions.set_prop('svn:eol-style', 'native', mu_path) 860 861 # A trailing newline should be added 862 svntest.actions.set_prop('svn:ignore', '*.o\nfoo.c', A_path) 863 svntest.actions.set_prop('svn:ignore', '*.o\nfoo.c\n', B_path) 864 865 # A trailing newline should be added 866 svntest.actions.set_prop('svn:externals', 'foo http://foo.com/repos', A_path) 867 svntest.actions.set_prop('svn:externals', 'foo http://foo.com/repos\n', B_path) 868 869 # Leading and trailing whitespace should be stripped, but not internal 870 # whitespace 871 svntest.actions.set_prop('svn:keywords', ' Rev Date \n', iota_path) 872 svntest.actions.set_prop('svn:keywords', 'Rev Date', mu_path) 873 874 # svn:executable value should be forced to a '*' 875 svntest.actions.set_prop('svn:executable', 'foo', iota_path) 876 svntest.actions.set_prop('svn:executable', '*', lambda_path) 877 for pval in (' ', '', 'no', 'off', 'false'): 878 svntest.actions.set_prop('svn:executable', pval, mu_path, 879 "svn: warning: W125005.*use 'svn propdel'") 880 881 # Anything else should be untouched 882 svntest.actions.set_prop('svn:some-prop', 'bar', lambda_path, force=True) 883 svntest.actions.set_prop('svn:some-prop', ' bar baz', mu_path, force=True) 884 svntest.actions.set_prop('svn:some-prop', 'bar\n', iota_path, force=True) 885 svntest.actions.set_prop('some-prop', 'bar', lambda_path) 886 svntest.actions.set_prop('some-prop', ' bar baz', mu_path) 887 svntest.actions.set_prop('some-prop', 'bar\n', iota_path) 888 889 # NOTE: When writing out multi-line prop values in svn:* props, the 890 # client converts to local encoding and local eol style. 891 # Therefore, the expected output must contain the right kind of eoln 892 # strings. That's why we use os.linesep in the tests below, not just 893 # plain '\n'. The _last_ \n is also from the client, but it's not 894 # part of the prop value and it doesn't get converted in the pipe. 895 896 # Check svn:mime-type 897 svntest.actions.check_prop('svn:mime-type', iota_path, [b'text/html']) 898 svntest.actions.check_prop('svn:mime-type', mu_path, [b'text/html']) 899 900 # Check svn:eol-style 901 svntest.actions.check_prop('svn:eol-style', iota_path, [b'native']) 902 svntest.actions.check_prop('svn:eol-style', mu_path, [b'native']) 903 904 # Check svn:ignore 905 linesep = os.linesep.encode() 906 svntest.actions.check_prop('svn:ignore', A_path, 907 [b'*.o'+linesep, b'foo.c'+linesep]) 908 svntest.actions.check_prop('svn:ignore', B_path, 909 [b'*.o'+linesep, b'foo.c'+linesep]) 910 911 # Check svn:externals 912 svntest.actions.check_prop('svn:externals', A_path, 913 [b'foo http://foo.com/repos'+linesep]) 914 svntest.actions.check_prop('svn:externals', B_path, 915 [b'foo http://foo.com/repos'+linesep]) 916 917 # Check svn:keywords 918 svntest.actions.check_prop('svn:keywords', iota_path, [b'Rev Date']) 919 svntest.actions.check_prop('svn:keywords', mu_path, [b'Rev Date']) 920 921 # Check svn:executable 922 svntest.actions.check_prop('svn:executable', iota_path, [b'*']) 923 svntest.actions.check_prop('svn:executable', lambda_path, [b'*']) 924 svntest.actions.check_prop('svn:executable', mu_path, [b'*']) 925 926 # Check other props 927 svntest.actions.check_prop('svn:some-prop', lambda_path, [b'bar']) 928 svntest.actions.check_prop('svn:some-prop', mu_path, [b' bar baz']) 929 svntest.actions.check_prop('svn:some-prop', iota_path, [b'bar'+linesep]) 930 svntest.actions.check_prop('some-prop', lambda_path, [b'bar']) 931 svntest.actions.check_prop('some-prop', mu_path,[b' bar baz']) 932 svntest.actions.check_prop('some-prop', iota_path, [b'bar\n']) 933 934 935#---------------------------------------------------------------------- 936 937def binary_props(sbox): 938 "test binary property support" 939 940 # Bootstrap 941 sbox.build() 942 wc_dir = sbox.wc_dir 943 944 # Make a backup copy of the working copy 945 wc_backup = sbox.add_wc_path('backup') 946 svntest.actions.duplicate_dir(wc_dir, wc_backup) 947 948 # Some path convenience vars. 949 A_path = sbox.ospath('A') 950 B_path = sbox.ospath('A/B') 951 iota_path = sbox.ospath('iota') 952 lambda_path = sbox.ospath('A/B/lambda') 953 mu_path = sbox.ospath('A/mu') 954 955 A_path_bak = sbox.ospath('A', wc_dir=wc_backup) 956 B_path_bak = sbox.ospath('A/B', wc_dir=wc_backup) 957 iota_path_bak = sbox.ospath('iota', wc_dir=wc_backup) 958 lambda_path_bak = sbox.ospath('A/B/lambda', wc_dir=wc_backup) 959 mu_path_bak = sbox.ospath('A/mu', wc_dir=wc_backup) 960 961 # Property value convenience vars. 962 prop_zb = b"This property has a zer\000 byte." 963 prop_ff = b"This property has a form\014feed." 964 prop_xml = b"This property has an <xml> tag." 965 prop_binx = b"This property has an <xml> tag and a zer\000 byte." 966 967 # Set some binary properties. 968 svntest.actions.set_prop('prop_zb', prop_zb, B_path, ) 969 svntest.actions.set_prop('prop_ff', prop_ff, iota_path) 970 svntest.actions.set_prop('prop_xml', prop_xml, lambda_path) 971 svntest.actions.set_prop('prop_binx', prop_binx, mu_path) 972 svntest.actions.set_prop('prop_binx', prop_binx, A_path) 973 974 # Create expected output and status trees. 975 expected_output = svntest.wc.State(wc_dir, { 976 'A' : Item(verb='Sending'), 977 'A/B' : Item(verb='Sending'), 978 'iota' : Item(verb='Sending'), 979 'A/B/lambda' : Item(verb='Sending'), 980 'A/mu' : Item(verb='Sending'), 981 }) 982 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 983 expected_status.tweak('A', 'A/B', 'iota', 'A/B/lambda', 'A/mu', 984 wc_rev=2, status=' ') 985 986 # Commit the propsets. 987 svntest.actions.run_and_verify_commit(wc_dir, 988 expected_output, 989 expected_status) 990 991 # Create expected output, disk, and status trees for an update of 992 # the wc_backup. 993 expected_output = svntest.wc.State(wc_backup, { 994 'A' : Item(status=' U'), 995 'A/B' : Item(status=' U'), 996 'iota' : Item(status=' U'), 997 'A/B/lambda' : Item(status=' U'), 998 'A/mu' : Item(status=' U'), 999 }) 1000 expected_disk = svntest.main.greek_state.copy() 1001 expected_status = svntest.actions.get_virginal_state(wc_backup, 2) 1002 1003 # Do the update and check the results. 1004 svntest.actions.run_and_verify_update(wc_backup, 1005 expected_output, 1006 expected_disk, 1007 expected_status) 1008 1009 # Now, check those properties. 1010 svntest.actions.check_prop('prop_zb', B_path_bak, [prop_zb]) 1011 svntest.actions.check_prop('prop_ff', iota_path_bak, [prop_ff]) 1012 svntest.actions.check_prop('prop_xml', lambda_path_bak, [prop_xml]) 1013 svntest.actions.check_prop('prop_binx', mu_path_bak, [prop_binx]) 1014 svntest.actions.check_prop('prop_binx', A_path_bak, [prop_binx]) 1015 1016#---------------------------------------------------------------------- 1017 1018# Ensure that each line of output contains the corresponding string of 1019# expected_out, and that errput is empty. 1020def verify_output(expected_out, output, errput): 1021 if errput != []: 1022 logger.warn('Error: stderr:') 1023 logger.warn(errput) 1024 raise svntest.Failure 1025 output.sort() 1026 ln = 0 1027 for line in output: 1028 if line.startswith('DBG:'): 1029 continue 1030 if ((line.find(expected_out[ln]) == -1) or 1031 (line != '' and expected_out[ln] == '')): 1032 logger.warn('Error: expected keywords: %s', expected_out) 1033 logger.warn(' actual full output: %s', output) 1034 raise svntest.Failure 1035 ln = ln + 1 1036 if ln != len(expected_out): 1037 raise svntest.Failure 1038 1039@Issue(1794) 1040def recursive_base_wc_ops(sbox): 1041 "recursive property operations in BASE and WC" 1042 1043 # Bootstrap 1044 sbox.build() 1045 wc_dir = sbox.wc_dir 1046 1047 # Files with which to test, in alphabetical order 1048 fp_add = sbox.ospath('A/added') 1049 fp_del = sbox.ospath('A/mu') 1050 #fp_keep= sbox.ospath('iota') 1051 1052 # Set up properties 1053 sbox.simple_propset('p', 'old-del', 'A/mu') 1054 sbox.simple_propset('p', 'old-keep', 'iota') 1055 sbox.simple_commit() 1056 1057 svntest.main.file_append(fp_add, 'blah') 1058 sbox.simple_add('A/added') 1059 sbox.simple_propset('p', 'new-add', 'A/added') 1060 sbox.simple_propset('p', 'new-del', 'A/mu') 1061 sbox.simple_propset('p', 'new-keep', 'iota') 1062 svntest.main.run_svn(None, 'del', '--force', fp_del) 1063 1064 # Test recursive proplist 1065 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', '-R', 1066 '-v', wc_dir, '-rBASE') 1067 verify_output([ 'old-del', 'old-keep', 'p', 'p', 1068 'Properties on ', 'Properties on ' ], 1069 output, errput) 1070 svntest.verify.verify_exit_code(None, exit_code, 0) 1071 1072 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', '-R', 1073 '-v', wc_dir) 1074 verify_output([ 'new-add', 'new-keep', 'p', 'p', 1075 'Properties on ', 'Properties on ' ], 1076 output, errput) 1077 svntest.verify.verify_exit_code(None, exit_code, 0) 1078 1079 # Test recursive propget 1080 exit_code, output, errput = svntest.main.run_svn(None, 'propget', '-R', 1081 'p', wc_dir, '-rBASE') 1082 verify_output([ 'old-del', 'old-keep' ], output, errput) 1083 svntest.verify.verify_exit_code(None, exit_code, 0) 1084 1085 exit_code, output, errput = svntest.main.run_svn(None, 'propget', '-R', 1086 'p', wc_dir) 1087 verify_output([ 'new-add', 'new-keep' ], output, errput) 1088 svntest.verify.verify_exit_code(None, exit_code, 0) 1089 1090 # Test recursive propset (issue 1794) 1091 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 1092 expected_status.tweak('A/mu', status='D ', wc_rev=2) 1093 expected_status.tweak('iota', status=' M', wc_rev=2) 1094 expected_status.add({ 1095 'A/added' : Item(status='A ', wc_rev=0), 1096 }) 1097 svntest.actions.run_and_verify_status(wc_dir, expected_status) 1098 1099 svntest.actions.run_and_verify_svn(None, [], 1100 'propset', '-R', 'svn:keywords', 'Date', 1101 os.path.join(wc_dir, 'A', 'B')) 1102 expected_status.tweak('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta', status=' M') 1103 svntest.actions.run_and_verify_status(wc_dir, expected_status) 1104 1105#---------------------------------------------------------------------- 1106 1107def url_props_ops(sbox): 1108 "property operations on a URL" 1109 1110 # Bootstrap 1111 sbox.build() 1112 wc_dir = sbox.wc_dir 1113 1114 prop1 = 'prop1' 1115 propval1 = 'propval1 is foo' 1116 prop2 = 'prop2' 1117 propval2 = 'propval2' 1118 1119 iota_url = sbox.repo_url + '/iota' 1120 A_url = sbox.repo_url + '/A' 1121 1122 # Add a couple of properties 1123 sbox.simple_propset(prop1, propval1, 'iota') 1124 sbox.simple_propset(prop1, propval1, 'A') 1125 1126 # Commit 1127 sbox.simple_commit() 1128 1129 # Add a few more properties 1130 sbox.simple_propset(prop2, propval2, 'iota') 1131 sbox.simple_propset(prop2, propval2, 'A') 1132 1133 # Commit again 1134 sbox.simple_commit() 1135 1136 # Test propget 1137 svntest.actions.run_and_verify_svn([ propval1 + '\n' ], [], 1138 'propget', prop1, iota_url) 1139 svntest.actions.run_and_verify_svn([ propval1 + '\n' ], [], 1140 'propget', prop1, A_url) 1141 1142 # Test normal proplist 1143 exit_code, output, errput = svntest.main.run_svn(None, 1144 'proplist', iota_url) 1145 verify_output([ prop1, prop2, 'Properties on ' ], 1146 output, errput) 1147 svntest.verify.verify_exit_code(None, exit_code, 0) 1148 1149 exit_code, output, errput = svntest.main.run_svn(None, 1150 'proplist', A_url) 1151 verify_output([ prop1, prop2, 'Properties on ' ], 1152 output, errput) 1153 svntest.verify.verify_exit_code(None, exit_code, 0) 1154 1155 # Test verbose proplist 1156 exit_code, output, errput = svntest.main.run_svn(None, 1157 'proplist', '-v', iota_url) 1158 verify_output([ propval1, propval2, prop1, prop2, 1159 'Properties on ' ], output, errput) 1160 svntest.verify.verify_exit_code(None, exit_code, 0) 1161 1162 exit_code, output, errput = svntest.main.run_svn(None, 1163 'proplist', '-v', A_url) 1164 verify_output([ propval1, propval2, prop1, prop2, 1165 'Properties on ' ], output, errput) 1166 svntest.verify.verify_exit_code(None, exit_code, 0) 1167 1168 # Test propedit 1169 svntest.main.use_editor('foo_to_bar') 1170 propval1 = propval1.replace('foo', 'bar') 1171 svntest.main.run_svn(None, 1172 'propedit', prop1, '-m', 'editlog', iota_url) 1173 svntest.main.run_svn(None, 1174 'propedit', prop1, '-m', 'editlog', A_url) 1175 svntest.actions.run_and_verify_svn([ propval1 + '\n' ], [], 1176 'propget', prop1, iota_url) 1177 svntest.actions.run_and_verify_svn([ propval1 + '\n' ], [], 1178 'propget', prop1, A_url) 1179 1180 # Edit without actually changing the property 1181 svntest.main.use_editor('identity') 1182 svntest.actions.run_and_verify_svn("No changes to property '%s' on '.*'" 1183 % prop1, 1184 [], 1185 'propedit', prop1, '-m', 'nocommit', 1186 iota_url) 1187 1188 1189 1190#---------------------------------------------------------------------- 1191def removal_schedule_added_props(sbox): 1192 "removal of schedule added file with properties" 1193 1194 sbox.build() 1195 1196 wc_dir = sbox.wc_dir 1197 newfile_path = sbox.ospath('newfile') 1198 file_add_output = ["A " + newfile_path + "\n"] 1199 propset_output = ["property 'newprop' set on '" + newfile_path + "'\n"] 1200 file_rm_output = ["D " + newfile_path + "\n"] 1201 propls_output = [ 1202 "Properties on '" + newfile_path + "':\n", 1203 " newprop\n", 1204 " newvalue\n", 1205 ] 1206 1207 # create new fs file 1208 open(newfile_path, 'w').close() 1209 # Add it and set a property 1210 svntest.actions.run_and_verify_svn(file_add_output, [], 'add', newfile_path) 1211 svntest.actions.run_and_verify_svn(propset_output, [], 'propset', 1212 'newprop', 'newvalue', newfile_path) 1213 svntest.actions.run_and_verify_svn(propls_output, [], 1214 'proplist', '-v', newfile_path) 1215 # remove the file 1216 svntest.actions.run_and_verify_svn(file_rm_output, [], 1217 'rm', '--force', newfile_path) 1218 # recreate the file and add it again 1219 open(newfile_path, 'w').close() 1220 svntest.actions.run_and_verify_svn(file_add_output, [], 'add', newfile_path) 1221 1222 # Now there should be NO properties leftover... 1223 svntest.actions.run_and_verify_svn([], [], 1224 'proplist', '-v', newfile_path) 1225 1226#---------------------------------------------------------------------- 1227 1228def update_props_on_wc_root(sbox): 1229 "receive properties on the wc root via update" 1230 1231 # Bootstrap 1232 sbox.build() 1233 wc_dir = sbox.wc_dir 1234 1235 # Make a backup copy of the working copy 1236 wc_backup = sbox.add_wc_path('backup') 1237 svntest.actions.duplicate_dir(wc_dir, wc_backup) 1238 1239 # Add a property to the root folder 1240 sbox.simple_propset('red', 'rojo', '') 1241 1242 # Create expected output tree. 1243 expected_output = svntest.wc.State(wc_dir, { 1244 '' : Item(verb='Sending') 1245 }) 1246 1247 # Created expected status tree. 1248 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 1249 expected_status.tweak('', wc_rev=2, status=' ') 1250 1251 # Commit the working copy 1252 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 1253 expected_status) 1254 1255 # Create expected output tree for an update of the wc_backup. 1256 expected_output = svntest.wc.State(wc_backup, { 1257 '' : Item(status=' U'), 1258 }) 1259 # Create expected disk tree for the update. 1260 expected_disk = svntest.main.greek_state.copy() 1261 expected_disk.add({ 1262 '' : Item(props = {'red' : 'rojo'}), 1263 }) 1264 # Create expected status tree for the update. 1265 expected_status = svntest.actions.get_virginal_state(wc_backup, 2) 1266 expected_status.tweak('', status=' ') 1267 1268 # Do the update and check the results in three ways... INCLUDING PROPS 1269 svntest.actions.run_and_verify_update(wc_backup, 1270 expected_output, 1271 expected_disk, 1272 expected_status, 1273 check_props=True) 1274 1275# test for issue 2743 1276@Issue(2743) 1277def props_on_replaced_file(sbox): 1278 """test properties on replaced files""" 1279 1280 sbox.build() 1281 wc_dir = sbox.wc_dir 1282 1283 # Add some properties to iota 1284 iota_path = sbox.ospath("iota") 1285 sbox.simple_propset('red', 'rojo', 'iota') 1286 sbox.simple_propset('blue', 'lagoon', 'iota') 1287 sbox.simple_commit() 1288 1289 # replace iota_path 1290 sbox.simple_rm('iota') 1291 svntest.main.file_append(iota_path, "some mod") 1292 sbox.simple_add('iota') 1293 1294 # check that the replaced file has no properties 1295 expected_disk = svntest.main.greek_state.copy() 1296 expected_disk.tweak('iota', contents="some mod") 1297 svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) 1298 1299 # now add a new property to iota 1300 sbox.simple_propset('red', 'mojo', 'iota') 1301 sbox.simple_propset('groovy', 'baby', 'iota') 1302 1303 # What we expect the disk tree to look like: 1304 expected_disk.tweak('iota', props={'red' : 'mojo', 'groovy' : 'baby'}) 1305 svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) 1306 1307#---------------------------------------------------------------------- 1308 1309def depthy_wc_proplist(sbox): 1310 """test proplist at various depths on a wc""" 1311 # Bootstrap. 1312 sbox.build() 1313 wc_dir = sbox.wc_dir 1314 1315 # Set up properties. 1316 sbox.simple_propset('p', 'prop1', '') 1317 sbox.simple_propset('p', 'prop2', 'iota') 1318 sbox.simple_propset('p', 'prop3', 'A') 1319 sbox.simple_propset('p', 'prop4', 'A/mu') 1320 1321 # Commit. 1322 sbox.simple_commit() 1323 1324 # Test depth-empty proplist. 1325 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', 1326 '--depth', 'empty', 1327 '-v', wc_dir) 1328 verify_output([ 'prop1', 'p', 'Properties on ' ], 1329 output, errput) 1330 svntest.verify.verify_exit_code(None, exit_code, 0) 1331 1332 # Test depth-files proplist. 1333 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', 1334 '--depth', 'files', 1335 '-v', wc_dir) 1336 verify_output([ 'prop1', 'prop2', 'p', 'p', 1337 'Properties on ', 'Properties on ' ], 1338 output, errput) 1339 svntest.verify.verify_exit_code(None, exit_code, 0) 1340 1341 # Test depth-immediates proplist. 1342 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', '--depth', 1343 'immediates', '-v', wc_dir) 1344 verify_output([ 'prop1', 'prop2', 'prop3' ] + 1345 ['p'] * 3 + ['Properties on '] * 3, 1346 output, errput) 1347 svntest.verify.verify_exit_code(None, exit_code, 0) 1348 1349 # Test depth-infinity proplist. 1350 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', '--depth', 1351 'infinity', '-v', wc_dir) 1352 verify_output([ 'prop1', 'prop2', 'prop3', 'prop4' ] + 1353 ['p'] * 4 + ['Properties on '] * 4, 1354 output, errput) 1355 svntest.verify.verify_exit_code(None, exit_code, 0) 1356 1357#---------------------------------------------------------------------- 1358 1359def depthy_url_proplist(sbox): 1360 """test proplist at various depths on a url""" 1361 # Bootstrap. 1362 sbox.build() 1363 repo_url = sbox.repo_url 1364 wc_dir = sbox.wc_dir 1365 1366 # Set up properties. 1367 sbox.simple_propset('p', 'prop1', '') 1368 sbox.simple_propset('p', 'prop2', 'iota') 1369 sbox.simple_propset('p', 'prop3', 'A') 1370 sbox.simple_propset('p', 'prop4', 'A/mu') 1371 sbox.simple_commit() 1372 1373 # Test depth-empty proplist. 1374 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', 1375 '--depth', 'empty', 1376 '-v', repo_url) 1377 verify_output([ 'prop1', 'p', 'Properties on '], 1378 output, errput) 1379 svntest.verify.verify_exit_code(None, exit_code, 0) 1380 1381 # Test depth-files proplist. 1382 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', 1383 '--depth', 'files', 1384 '-v', repo_url) 1385 verify_output([ 'prop1', 'prop2', 'p', 'p', 1386 'Properties on ', 'Properties on ' ], 1387 output, errput) 1388 svntest.verify.verify_exit_code(None, exit_code, 0) 1389 1390 # Test depth-immediates proplist. 1391 exit_code, output, errput = svntest.main.run_svn(None, 'proplist', 1392 '--depth', 'immediates', 1393 '-v', repo_url) 1394 1395 verify_output([ 'prop1', 'prop2', 'prop3' ] + ['p'] * 3 + 1396 ['Properties on '] * 3, 1397 output, errput) 1398 svntest.verify.verify_exit_code(None, exit_code, 0) 1399 1400 # Test depth-infinity proplist. 1401 exit_code, output, errput = svntest.main.run_svn(None, 1402 'proplist', '--depth', 1403 'infinity', '-v', repo_url) 1404 verify_output([ 'prop1', 'prop2', 'prop3', 'prop4' ] + ['p'] * 4 + 1405 ['Properties on '] * 4, 1406 output, errput) 1407 svntest.verify.verify_exit_code(None, exit_code, 0) 1408 1409#---------------------------------------------------------------------- 1410 1411def invalid_propnames(sbox): 1412 """test prop* handle invalid property names""" 1413 # Bootstrap. 1414 sbox.build() 1415 repo_url = sbox.repo_url 1416 wc_dir = sbox.wc_dir 1417 cwd = os.getcwd() 1418 os.chdir(wc_dir) 1419 1420 propname = chr(8) 1421 propval = 'foo' 1422 1423 expected_stdout = (".*Attempting to delete nonexistent property " 1424 "'%s'.*" % (propname,)) 1425 svntest.actions.run_and_verify_svn(expected_stdout, [], 1426 'propdel', propname) 1427 expected_stderr = (".*'%s' is not a valid Subversion" 1428 ' property name' % (propname,)) 1429 svntest.actions.run_and_verify_svn(None, expected_stderr, 1430 'propedit', propname) 1431 svntest.actions.run_and_verify_svn(None, expected_stderr, 1432 'propget', propname) 1433 svntest.actions.run_and_verify_svn(None, expected_stderr, 1434 'propset', propname, propval) 1435 1436 svntest.actions.run_and_verify_svn(None, expected_stderr, 1437 'commit', '--with-revprop', 1438 '='.join([propname, propval])) 1439 # Now swap them: --with-revprop should accept propname as a property 1440 # value; no concept of validity there. 1441 svntest.actions.run_and_verify_svn([], [], 1442 'commit', '--with-revprop', 1443 '='.join([propval, propname])) 1444 1445 os.chdir(cwd) 1446 1447@SkipUnless(svntest.main.is_posix_os) 1448@Issue(2581) 1449def perms_on_symlink(sbox): 1450 "propset shouldn't touch symlink perms" 1451 sbox.build() 1452 # We can't just run commands on absolute paths in the usual way 1453 # (e.g., os.path.join(sbox.wc_dir, 'newdir')), because for some 1454 # reason, if the symlink points to newdir as an absolute path, the 1455 # bug doesn't reproduce. I have no idea why. Since it does have to 1456 # point to newdir, the only other choice is to have it point to it 1457 # in the same directory, so we have to run the test from inside the 1458 # working copy. 1459 saved_cwd = os.getcwd() 1460 os.chdir(sbox.wc_dir) 1461 try: 1462 svntest.actions.run_and_verify_svn(None, [], 'mkdir', 'newdir') 1463 os.symlink('newdir', 'symlink') 1464 svntest.actions.run_and_verify_svn(None, [], 'add', 'symlink') 1465 old_mode = os.stat('newdir')[stat.ST_MODE] 1466 # The only property on 'symlink' is svn:special, so attempting to remove 1467 # 'svn:executable' should result in an error 1468 expected_stdout = (".*Attempting to delete nonexistent property " 1469 "'svn:executable'.*") 1470 svntest.actions.run_and_verify_svn(expected_stdout, [], 'propdel', 1471 'svn:executable', 'symlink') 1472 new_mode = os.stat('newdir')[stat.ST_MODE] 1473 if not old_mode == new_mode: 1474 # Chmod newdir back, so the test suite can remove this working 1475 # copy when cleaning up later. 1476 os.chmod('newdir', stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) 1477 raise svntest.Failure 1478 finally: 1479 os.chdir(saved_cwd) 1480 1481# Use a property with a custom namespace, ie 'ns:prop' or 'mycompany:prop'. 1482def remove_custom_ns_props(sbox): 1483 "remove a property with a custom namespace" 1484 1485 # Bootstrap 1486 sbox.build() 1487 wc_dir = sbox.wc_dir 1488 1489 # Add a property to a file 1490 sbox.simple_propset('ns:cash-sound', 'cha-ching!', 'iota') 1491 1492 # Commit the file 1493 sbox.simple_commit('iota') 1494 1495 # Now, make a backup copy of the working copy 1496 wc_backup = sbox.add_wc_path('backup') 1497 svntest.actions.duplicate_dir(wc_dir, wc_backup) 1498 1499 # Remove the property 1500 sbox.simple_propdel('ns:cash-sound', 'iota') 1501 1502 # Create expected trees. 1503 expected_output = svntest.wc.State(wc_dir, { 1504 'iota' : Item(verb='Sending'), 1505 }) 1506 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 1507 expected_status.tweak('iota', wc_rev=3, status=' ') 1508 1509 # Commit the one file. 1510 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 1511 expected_status) 1512 1513 # Create expected trees for the update. 1514 expected_output = svntest.wc.State(wc_backup, { 1515 'iota' : Item(status=' U'), 1516 }) 1517 expected_disk = svntest.main.greek_state.copy() 1518 expected_status = svntest.actions.get_virginal_state(wc_backup, 3) 1519 expected_status.tweak('iota', wc_rev=3, status=' ') 1520 1521 # Do the update and check the results in three ways... INCLUDING PROPS 1522 svntest.actions.run_and_verify_update(wc_backup, 1523 expected_output, 1524 expected_disk, 1525 expected_status, 1526 check_props=True) 1527 1528def props_over_time(sbox): 1529 "property retrieval with peg and operative revs" 1530 1531 # Bootstrap 1532 sbox.build() 1533 wc_dir = sbox.wc_dir 1534 1535 # Convenience variables 1536 iota_path = sbox.ospath('iota') 1537 iota_url = sbox.repo_url + '/iota' 1538 1539 # Add/tweak a property 'revision' with value revision-committed to a 1540 # file, commit, and then repeat this a few times. 1541 for rev in range(2, 4): 1542 sbox.simple_propset('revision', str(rev), 'iota') 1543 sbox.simple_commit('iota') 1544 1545 # Backdate to r2 so the defaults for URL- vs. WC-style queries are 1546 # different. 1547 svntest.main.run_svn(None, 'up', '-r2', wc_dir) 1548 1549 # Now, test propget of the property across many combinations of 1550 # pegrevs, operative revs, and wc-path vs. url style input specs. 1551 # NOTE: We're using 0 in these loops to mean "unspecified". 1552 for path in iota_path, iota_url: 1553 for peg_rev in range(0, 4): 1554 for op_rev in range(0, 4): 1555 # Calculate the expected property value. If there is an 1556 # operative rev, we expect the output to match revisions 1557 # there. Else, we'll be looking at the peg-rev value. And if 1558 # neither are supplied, it depends on the path vs. URL 1559 # question. 1560 if op_rev > 1: 1561 expected = str(op_rev) 1562 elif op_rev == 1: 1563 expected = None 1564 else: 1565 if peg_rev > 1: 1566 expected = str(peg_rev) 1567 elif peg_rev == 1: 1568 expected = None 1569 else: 1570 if path == iota_url: 1571 expected = "3" # HEAD 1572 else: 1573 expected = "2" # BASE 1574 1575 peg_path = path + (peg_rev != 0 and '@' + str(peg_rev) or "") 1576 1577 ### Test 'svn propget' 1578 pget_expected = expected 1579 if pget_expected: 1580 pget_expected = [ pget_expected + "\n" ] 1581 expected_err = [] if expected else '.*W200017: Property.*not found.*' 1582 if op_rev != 0: 1583 svntest.actions.run_and_verify_svn(pget_expected, expected_err, 1584 'propget', 'revision', peg_path, 1585 '-r', str(op_rev)) 1586 else: 1587 svntest.actions.run_and_verify_svn(pget_expected, expected_err, 1588 'propget', 'revision', peg_path) 1589 1590 ### Test 'svn proplist -v' 1591 if op_rev != 0 or peg_rev != 0: # a revision-ful query output URLs 1592 path = iota_url 1593 plist_expected = expected 1594 if plist_expected: 1595 plist_expected = [ "Properties on '" + path + "':\n", 1596 " revision\n", 1597 " " + expected + "\n" ] 1598 1599 if op_rev != 0: 1600 svntest.actions.run_and_verify_svn(plist_expected, [], 1601 'proplist', '-v', peg_path, 1602 '-r', str(op_rev)) 1603 else: 1604 svntest.actions.run_and_verify_svn(plist_expected, [], 1605 'proplist', '-v', peg_path) 1606 1607 1608# XFail the same reason revprop_change() is. 1609@SkipUnless(svntest.main.server_enforces_date_syntax) 1610@Issue(3086) 1611def invalid_propvalues(sbox): 1612 "test handling invalid svn:* property values" 1613 1614 sbox.build(create_wc = False) 1615 repo_dir = sbox.repo_dir 1616 repo_url = sbox.repo_url 1617 1618 svntest.actions.enable_revprop_changes(repo_dir) 1619 1620 expected_stderr = '.*unexpected property value.*|.*Bogus date.*' 1621 svntest.actions.run_and_verify_svn([], expected_stderr, 1622 'propset', '--revprop', '-r', '0', 1623 'svn:date', 'Sat May 10 12:12:31 2008', 1624 repo_url) 1625 1626@Issue(3282) 1627def same_replacement_props(sbox): 1628 "commit replacement props when same as old props" 1629 # issue #3282 1630 sbox.build() 1631 1632 foo_path = sbox.ospath('foo') 1633 1634 open(foo_path, 'w').close() 1635 sbox.simple_add('foo') 1636 sbox.simple_propset('someprop', 'someval', 'foo') 1637 sbox.simple_commit('foo') 1638 sbox.simple_rm('foo') 1639 1640 # Now replace 'foo'. 1641 open(foo_path, 'w').close() 1642 sbox.simple_add('foo') 1643 1644 # Set the same property again, with the same value. 1645 sbox.simple_propset('someprop', 'someval', 'foo') 1646 sbox.simple_commit('foo') 1647 1648 # Check if the property made it into the repository. 1649 foo_url = sbox.repo_url + '/foo' 1650 expected_out = [ "Properties on '" + foo_url + "':\n", 1651 " someprop\n", 1652 " someval\n" ] 1653 svntest.actions.run_and_verify_svn(expected_out, [], 1654 'proplist', '-v', foo_url) 1655 1656def added_moved_file(sbox): 1657 "'svn mv added_file' preserves props" 1658 1659 sbox.build() 1660 wc_dir = sbox.wc_dir 1661 1662 # create it 1663 foo_path = sbox.ospath('foo') 1664 foo2_path = sbox.ospath('foo2') 1665 foo2_url = sbox.repo_url + '/foo2' 1666 1667 open(foo_path, 'w').close() 1668 1669 # add it 1670 sbox.simple_add('foo') 1671 sbox.simple_propset('someprop', 'someval', 'foo') 1672 1673 # move it 1674 svntest.main.run_svn(None, 'mv', foo_path, foo2_path) 1675 1676 # should still have the property 1677 svntest.actions.check_prop('someprop', foo2_path, [b'someval']) 1678 1679 # the property should get committed, too 1680 sbox.simple_commit() 1681 svntest.actions.check_prop('someprop', foo2_url, [b'someval']) 1682 1683 1684# Issue 2220, deleting a non-existent property should error 1685@Issue(2220) 1686def delete_nonexistent_property(sbox): 1687 "remove a property which doesn't exist" 1688 1689 # Bootstrap 1690 sbox.build() 1691 wc_dir = sbox.wc_dir 1692 1693 # Remove one property 1694 expected_stdout = ".*Attempting to delete nonexistent property 'yellow'.*" 1695 svntest.actions.run_and_verify_svn(expected_stdout, [], 1696 'propdel', 'yellow', 1697 os.path.join(wc_dir, 'A', 'D', 'G')) 1698 1699#---------------------------------------------------------------------- 1700@Issue(3553) 1701def post_revprop_change_hook(sbox): 1702 "post-revprop-change hook" 1703 1704 sbox.build() 1705 wc_dir = sbox.wc_dir 1706 repo_dir = sbox.repo_dir 1707 1708 # Include a non-XML-safe message to regression-test issue #3553. 1709 error_msg = 'Text with <angle brackets> & ampersand' 1710 1711 svntest.actions.enable_revprop_changes(repo_dir) 1712 svntest.actions.create_failing_hook(repo_dir, 'post-revprop-change', 1713 error_msg) 1714 1715 # serf/mod_dav_svn give SVN_ERR_RA_DAV_PROPPATCH_FAILED 1716 # file/svn give SVN_ERR_REPOS_HOOK_FAILURE 1717 expected_error = 'svn: (E175008|E165001).*post-revprop-change hook failed' 1718 1719 svntest.actions.run_and_verify_svn([], expected_error, 1720 'ps', '--revprop', '-r0', 'p', 'v', 1721 wc_dir) 1722 1723 # Verify change has stuck -- at one time mod_dav_svn would rollback 1724 # revprop changes on post-revprop-change hook errors 1725 svntest.actions.run_and_verify_svn('v', [], 1726 'pg', '--revprop', '-r0', 'p', 1727 wc_dir) 1728 1729def rm_of_replaced_file(sbox): 1730 """properties after a removal of a replaced file""" 1731 1732 sbox.build() 1733 wc_dir = sbox.wc_dir 1734 1735 # Add some properties to iota and mu 1736 iota_path = sbox.ospath('iota') 1737 sbox.simple_propset('red', 'rojo', 'iota') 1738 sbox.simple_propset('blue', 'lagoon', 'iota') 1739 1740 mu_path = sbox.ospath('A/mu') 1741 sbox.simple_propset('yellow', 'submarine', 'A/mu') 1742 sbox.simple_propset('orange', 'toothpick', 'A/mu') 1743 1744 sbox.simple_commit() 1745 1746 # Copy iota over the top of mu 1747 sbox.simple_rm('A/mu') 1748 svntest.main.run_svn(None, 'cp', iota_path, mu_path) 1749 1750 expected_disk = svntest.main.greek_state.copy() 1751 expected_disk.tweak('iota', props={'red': 'rojo', 'blue': 'lagoon'}) 1752 expected_disk.tweak('A/mu', props={'red': 'rojo', 'blue': 'lagoon'}, 1753 contents="This is the file 'iota'.\n") 1754 svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) 1755 1756 # Remove the copy. This should leave the original locally-deleted mu, 1757 # which should have no properties. 1758 svntest.main.run_svn(None, 'rm', '--force', mu_path) 1759 1760 svntest.actions.run_and_verify_svn( 1761 [], 1762 'svn: E200009.*some targets are not versioned.*', 1763 'proplist', '-v', mu_path) 1764 1765 # Run it again, but ask for the pristine properties, which should 1766 # be mu's original props. 1767 exit_code, output, errput = svntest.main.run_svn(None, 1768 'proplist', '-v', 1769 mu_path + '@base') 1770 expected_output = svntest.verify.UnorderedRegexListOutput([ 1771 'Properties on.*', 1772 ' yellow', 1773 ' submarine', 1774 ' orange', 1775 ' toothpick', 1776 ]) 1777 svntest.verify.compare_and_display_lines('message', 'label', 1778 expected_output, output) 1779 svntest.verify.verify_exit_code(None, exit_code, 0) 1780 1781 1782def prop_reject_grind(sbox): 1783 """grind through all variants of prop rejects""" 1784 1785 sbox.build() 1786 wc_dir = sbox.wc_dir 1787 1788 mu_path = sbox.ospath('A/mu') 1789 mu_prej_path = sbox.ospath('A/mu.prej') 1790 1791 # Create r2 with all the properties we intend to use as incoming-change, 1792 # and as incoming-delete. Also set up our local-edit and local-delete 1793 # properties. We also need some properties that are simply different 1794 # from the incoming properties 1795 sbox.simple_propset('edit.diff', 'repos', 'iota') 1796 sbox.simple_propset('edit.edit', 'repos', 'iota') 1797 sbox.simple_propset('edit.del', 'repos', 'iota') 1798 sbox.simple_propset('edit.add', 'repos', 'iota') 1799 sbox.simple_propset('edit.none', 'repos', 'iota') 1800 sbox.simple_propset('del.edit', 'repos', 'iota') 1801 sbox.simple_propset('del.edit2', 'repos', 'iota') 1802 sbox.simple_propset('del.diff', 'repos', 'iota') 1803 sbox.simple_propset('del.del', 'repos', 'iota') 1804 sbox.simple_propset('del.add', 'repos', 'iota') 1805 1806 sbox.simple_propset('edit.edit', 'local', 'A/mu') 1807 sbox.simple_propset('add.edit', 'local', 'A/mu') 1808 sbox.simple_propset('del.edit', 'local', 'A/mu') 1809 sbox.simple_propset('del.edit2', 'repos', 'A/mu') 1810 sbox.simple_propset('add.del', 'local', 'A/mu') 1811 sbox.simple_propset('edit.del', 'local', 'A/mu') 1812 sbox.simple_propset('del.del', 'local', 'A/mu') 1813 sbox.simple_propset('edit.diff', 'local', 'A/mu') 1814 sbox.simple_propset('add.diff', 'local', 'A/mu') 1815 sbox.simple_propset('del.diff', 'local', 'A/mu') 1816 1817 sbox.simple_commit() 1818 1819 # Create r3 with all the properties that we intend to use as incoming-add, 1820 # and then perform the incoming-edits and incoming-deletes. 1821 sbox.simple_propset('add.add', 'repos', 'iota') 1822 sbox.simple_propset('add.edit', 'repos', 'iota') 1823 sbox.simple_propset('add.del', 'repos', 'iota') 1824 sbox.simple_propset('add.diff', 'repos', 'iota') 1825 sbox.simple_propset('edit.diff', 'repos.changed', 'iota') 1826 sbox.simple_propset('edit.edit', 'repos.changed', 'iota') 1827 sbox.simple_propset('edit.del', 'repos.changed', 'iota') 1828 sbox.simple_propset('edit.add', 'repos.changed', 'iota') 1829 sbox.simple_propset('edit.none', 'repos.changed', 'iota') 1830 sbox.simple_propdel('del.edit', 'iota') 1831 sbox.simple_propdel('del.edit2', 'iota') 1832 sbox.simple_propdel('del.diff', 'iota') 1833 sbox.simple_propdel('del.del', 'iota') 1834 sbox.simple_propdel('del.add', 'iota') 1835 sbox.simple_commit() 1836 1837 # Set up our victim for all the right rejects: local-adds, local-edits, 1838 # and local-deletes. 1839 sbox.simple_propset('edit.add', 'local', 'A/mu') 1840 sbox.simple_propset('add.add', 'local', 'A/mu') 1841 sbox.simple_propset('del.add', 'local', 'A/mu') 1842 sbox.simple_propset('edit.edit', 'local.changed', 'A/mu') 1843 sbox.simple_propset('add.edit', 'local.changed', 'A/mu') 1844 sbox.simple_propset('del.edit', 'local.changed', 'A/mu') 1845 sbox.simple_propset('del.edit2', 'repos.changed', 'A/mu') 1846 sbox.simple_propdel('add.del', 'A/mu') 1847 sbox.simple_propdel('edit.del', 'A/mu') 1848 sbox.simple_propdel('del.del', 'A/mu') 1849 1850 # Now merge r2:3 into the victim to create all variants 1851 svntest.main.run_svn(False, 'merge', '-r2:3', sbox.repo_url + '/iota', 1852 mu_path) 1853 1854 # Check that A/mu.prej reports the expected conflicts: 1855 expected_prej = [ 1856 "Trying to change property 'edit.none'\n" 1857 "but the property does not exist locally.\n" 1858 "<<<<<<< (local property value)\n" 1859 "||||||| (incoming 'changed from' value)\n" 1860 "repos=======\n" 1861 "repos.changed>>>>>>> (incoming 'changed to' value)\n", 1862 1863 "Trying to delete property 'del.del'\n" 1864 "but the property has been locally deleted and had a different value.\n", 1865 1866 "Trying to delete property 'del.edit'\n" 1867 "but the local property value is different.\n" 1868 "<<<<<<< (local property value)\n" 1869 "local.changed||||||| (incoming 'changed from' value)\n" 1870 "repos=======\n" 1871 ">>>>>>> (incoming 'changed to' value)\n", 1872 1873 "Trying to change property 'edit.del'\n" 1874 "but the property has been locally deleted.\n" 1875 "<<<<<<< (local property value)\n" 1876 "||||||| (incoming 'changed from' value)\n" 1877 "repos=======\n" 1878 "repos.changed>>>>>>> (incoming 'changed to' value)\n", 1879 1880 "Trying to change property 'edit.edit'\n" 1881 "but the property has already been locally changed to a different value.\n" 1882 "<<<<<<< (local property value)\n" 1883 "local.changed||||||| (incoming 'changed from' value)\n" 1884 "repos=======\n" 1885 "repos.changed>>>>>>> (incoming 'changed to' value)\n", 1886 1887 "Trying to delete property 'del.edit2'\n" 1888 "but the property has been locally modified.\n" 1889 "<<<<<<< (local property value)\n" 1890 "repos.changed||||||| (incoming 'changed from' value)\n" 1891 "repos=======\n" 1892 ">>>>>>> (incoming 'changed to' value)\n", 1893 1894 "Trying to delete property 'del.add'\n" 1895 "but the property has been locally added.\n" 1896 "<<<<<<< (local property value)\n" 1897 "local||||||| (incoming 'changed from' value)\n" 1898 "repos=======\n" 1899 ">>>>>>> (incoming 'changed to' value)\n", 1900 1901 "Trying to delete property 'del.diff'\n" 1902 "but the local property value is different.\n" 1903 "<<<<<<< (local property value)\n" 1904 "local||||||| (incoming 'changed from' value)\n" 1905 "repos=======\n" 1906 ">>>>>>> (incoming 'changed to' value)\n", 1907 1908 "Trying to change property 'edit.add'\n" 1909 "but the property has been locally added with a different value.\n" 1910 "<<<<<<< (local property value)\n" 1911 "local||||||| (incoming 'changed from' value)\n" 1912 "repos=======\n" 1913 "repos.changed>>>>>>> (incoming 'changed to' value)\n", 1914 1915 "Trying to change property 'edit.diff'\n" 1916 "but the local property value conflicts with the incoming change.\n" 1917 "<<<<<<< (local property value)\n" 1918 "local||||||| (incoming 'changed from' value)\n" 1919 "repos=======\n" 1920 "repos.changed>>>>>>> (incoming 'changed to' value)\n", 1921 1922 "Trying to add new property 'add.add'\n" 1923 "but the property already exists.\n" 1924 "<<<<<<< (local property value)\n" 1925 "local||||||| (incoming 'changed from' value)\n" 1926 "=======\n" 1927 "repos>>>>>>> (incoming 'changed to' value)\n", 1928 1929 "Trying to add new property 'add.diff'\n" 1930 "but the property already exists.\n" 1931 "<<<<<<< (local property value)\n" 1932 "local||||||| (incoming 'changed from' value)\n" 1933 "=======\n" 1934 "repos>>>>>>> (incoming 'changed to' value)\n", 1935 1936 "Trying to add new property 'add.del'\n" 1937 "but the property has been locally deleted.\n" 1938 "Incoming property value:\n" 1939 "repos\n", 1940 1941 "Trying to add new property 'add.edit'\n" 1942 "but the property already exists.\n" 1943 "<<<<<<< (local property value)\n" 1944 "local.changed||||||| (incoming 'changed from' value)\n" 1945 "=======\n" 1946 "repos>>>>>>> (incoming 'changed to' value)\n", 1947 ] 1948 1949 # Get the contents of mu.prej. The error messages are in the prej file 1950 # but there is no guarantee as to order. So try to locate each message 1951 # in the file individually. 1952 prej_file = open(mu_prej_path, 'r') 1953 n = 0 1954 for message in expected_prej: 1955 prej_file.seek(0) 1956 match = False 1957 i = 0 1958 j = 0 1959 msg_lines = message.split('\n') 1960 for file_line in prej_file: 1961 line = msg_lines[i] + '\n' 1962 match = (line == file_line) 1963 if match: 1964 # The last line in the list is always an empty string. 1965 if msg_lines[i + 1] == "": 1966 #logger.info("found message %i in file at line %i" % (n, j)) 1967 break 1968 i += 1 1969 else: 1970 i = 0 1971 j += 1 1972 n += 1 1973 if not match: 1974 raise svntest.main.SVNUnmatchedError( 1975 "Expected mu.prej doesn't match actual mu.prej") 1976 1977def obstructed_subdirs(sbox): 1978 """test properties of obstructed subdirectories""" 1979 1980 sbox.build() 1981 wc_dir = sbox.wc_dir 1982 1983 # at one point during development, obstructed subdirectories threw 1984 # errors trying to fetch property information during 'svn status'. 1985 # this test ensures we won't run into that problem again. 1986 1987 C_path = sbox.ospath('A/C') 1988 sbox.simple_propset('red', 'blue', 'A/C') 1989 1990 expected_disk = svntest.main.greek_state.copy() 1991 expected_disk.tweak('A/C', props={'red': 'blue'}) 1992 svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) 1993 1994 # Remove the subdir from disk, and validate the status 1995 svntest.main.safe_rmtree(C_path) 1996 1997 expected_disk.remove('A/C') 1998 svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) 1999 2000 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 2001 expected_status.tweak('A/C', status='!M', wc_rev='1') 2002 2003 svntest.actions.run_and_verify_status(wc_dir, expected_status) 2004 2005 # Drop an empty file there to obstruct the now-deleted subdir 2006 open(C_path, 'w') 2007 2008 expected_disk.add({'A/C': Item(contents='', props={'red': 'blue'})}) 2009 expected_status.tweak('A/C', status='~M', wc_rev='1') 2010 2011 svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) 2012 2013 2014 svntest.actions.run_and_verify_status(wc_dir, expected_status) 2015 2016 2017def atomic_over_ra(sbox): 2018 "test revprop atomicity guarantees of libsvn_ra" 2019 2020 sbox.build(create_wc=False) 2021 repo_url = sbox.repo_url 2022 2023 # From this point on, similar to ../libsvn_fs/fs-test.c:revision_props(). 2024 s1 = "violet" 2025 s2 = "wrong value" 2026 2027 # But test "" explicitly, since the RA layers have to marshal "" and <unset> 2028 # differently. 2029 s3 = "" 2030 2031 # Initial state. 2032 svntest.actions.enable_revprop_changes(sbox.repo_dir) 2033 svntest.actions.run_and_verify_svn(None, [], 2034 'propset', '--revprop', '-r', '0', 2035 'flower', s1, repo_url) 2036 2037 # Helpers. 2038 2039 def expect_old_server_fail(old_value, proposed_value): 2040 # We are setting a (possibly "not present") expectation for the old value, 2041 # so we should fail. 2042 expected_stderr = ".*doesn't advertise.*ATOMIC_REVPROP" 2043 svntest.actions.run_and_verify_atomic_ra_revprop_change( 2044 None, expected_stderr, 1, repo_url, 0, 'flower', 2045 old_value, proposed_value, True) 2046 2047 # The original value is still there. 2048 svntest.actions.check_prop('flower', repo_url, [s1], 0) 2049 2050 def FAILS_WITH_BPV(not_the_old_value, proposed_value): 2051 if svntest.main.server_has_atomic_revprop(): 2052 svntest.actions.run_and_verify_atomic_ra_revprop_change( 2053 None, [], 0, repo_url, 0, 'flower', 2054 not_the_old_value, proposed_value, True) 2055 else: 2056 expect_old_server_fail(not_the_old_value, proposed_value) 2057 2058 def PASSES_WITHOUT_BPV(yes_the_old_value, proposed_value): 2059 if svntest.main.server_has_atomic_revprop(): 2060 svntest.actions.run_and_verify_atomic_ra_revprop_change( 2061 None, [], 0, repo_url, 0, 'flower', 2062 yes_the_old_value, proposed_value, False) 2063 else: 2064 expect_old_server_fail(yes_the_old_value, proposed_value) 2065 2066 # Value of "flower" is 's1'. 2067 FAILS_WITH_BPV(s2, s1) 2068 FAILS_WITH_BPV(s3, s1) 2069 PASSES_WITHOUT_BPV(s1, s2) 2070 2071 # Value of "flower" is 's2'. 2072 PASSES_WITHOUT_BPV(s2, s3) 2073 2074 # Value of "flower" is 's3'. 2075 FAILS_WITH_BPV(None, s3) 2076 FAILS_WITH_BPV(s1, s3) 2077 PASSES_WITHOUT_BPV(s3, s2) 2078 2079 # Value of "flower" is 's2'. 2080 FAILS_WITH_BPV(None, None) 2081 FAILS_WITH_BPV(s1, None) 2082 FAILS_WITH_BPV(s3, None) 2083 PASSES_WITHOUT_BPV(s2, None) 2084 2085 # Value of "flower" is <not set>. 2086 FAILS_WITH_BPV(s2, s1) 2087 FAILS_WITH_BPV(s3, s1) 2088 PASSES_WITHOUT_BPV(None, s1) 2089 2090 # Value of "flower" is 's1'. 2091 svntest.actions.check_prop('flower', repo_url, [s1.encode()], 0) 2092 2093# Test for issue #3721 'redirection of svn propget output corrupted with 2094# large property values' 2095@Issue(3721) 2096def propget_redirection(sbox): 2097 """pg of large text properties redirects properly""" 2098 2099 sbox.build() 2100 wc_dir = sbox.wc_dir 2101 2102 # Some paths we'll care about 2103 B_path = os.path.join(wc_dir, "A", "B") 2104 C_path = os.path.join(wc_dir, "A", "C") 2105 D_path = os.path.join(wc_dir, "A", "D") 2106 2107 prop_val_file = os.path.join(wc_dir, "prop_val") 2108 redirect_file = os.path.join(wc_dir, "pg.vR.out") 2109 2110 # A 'big' mergeinfo property. Yes, it is bogus in the sense that 2111 # it refers to non-existent path-revs, but that is not relevant to 2112 # this test. What matters is that it is a realistic 'big' mergeinfo 2113 # value (it is from Subversion's own 1.6.x branch in fact). 2114 # Also, the syntax is wrong: every path should start with '/'; 2115 # Subversion currently silently corrects this. 2116 big_prop_val = "subversion/branches/1.5.x:872364-874936\n" + \ 2117 "subversion/branches/1.5.x-34184:874657-874741\n" + \ 2118 "subversion/branches/1.5.x-34432:874744-874798\n" + \ 2119 "subversion/branches/1.5.x-issue3067:872184-872314\n" + \ 2120 "subversion/branches/1.5.x-issue3157:872165-872175\n" + \ 2121 "subversion/branches/1.5.x-issue3174:872178-872348\n" + \ 2122 "subversion/branches/1.5.x-r30215:870310,870312,870319,870362\n" + \ 2123 "subversion/branches/1.5.x-r30756:874853-874870\n" + \ 2124 "subversion/branches/1.5.x-r30868:870951-870970\n" + \ 2125 "subversion/branches/1.5.x-r31314:874476-874605\n" + \ 2126 "subversion/branches/1.5.x-r31516:871592-871649\n" + \ 2127 "subversion/branches/1.5.x-r32470:872546-872676\n" + \ 2128 "subversion/branches/1.5.x-r32968:873773-873872\n" + \ 2129 "subversion/branches/1.5.x-r33447:873527-873547\n" + \ 2130 "subversion/branches/1.5.x-r33465:873541-873549\n" + \ 2131 "subversion/branches/1.5.x-r33641:873880-873883\n" + \ 2132 "subversion/branches/1.5.x-r34050-followups:874639-874686\n" + \ 2133 "subversion/branches/1.5.x-r34487:874562-874581\n" + \ 2134 "subversion/branches/1.5.x-ra_serf-backports:872354-872626\n" + \ 2135 "subversion/branches/1.5.x-rb-test-fix:874916-874919\n" + \ 2136 "subversion/branches/1.5.x-reintegrate-improvements:874586-874922\n" + \ 2137 "subversion/branches/1.5.x-tests-pass:870925-870973\n" + \ 2138 "subversion/branches/dont-save-plaintext-passwords-by-default:" + \ 2139 "870728-871118\n" + \ 2140 "subversion/branches/gnome-keyring:870558-871410\n" + \ 2141 "subversion/branches/issue-3220-dev:872210-872226\n" + \ 2142 "subversion/branches/kwallet:870785-871314\n" + \ 2143 "subversion/branches/log-g-performance:870941-871032\n" + \ 2144 "subversion/branches/r30963-1.5.x:871056-871076\n" + \ 2145 "subversion/branches/reintegrate-improvements:873853-874164\n" + \ 2146 "subversion/branches/svn-mergeinfo-enhancements:870196\n" + \ 2147 "subversion/branches/svnpatch-diff:871905\n" + \ 2148 "subversion/trunk:869159-869165,869168-869181,869185,869188,869191," + \ 2149 "869200-869201,869203-869207,869209-869224,869227-869238,869240-" + \ 2150 "869244,869248,869250-869260,869262-869263,869265,869267-869268," + \ 2151 "869272-869280,869282-869325,869328-869330,869335,869341-869347," + \ 2152 "869351,869354-869355,869358,869361-869377,869379-869381,869383-" + \ 2153 "869417,869419-869422,869432-869453,869455-869466,869471-869473," + \ 2154 "869475,869483,869486,869488-869489,869491-869497,869499-869500," + \ 2155 "869503,869506-869508,869510-869521,869523-869540,869542-869552," + \ 2156 "869556,869558,869560-869561,869563,869565,869567,869570,869572," + \ 2157 "869582,869601-869602,869605,869607,869613-869614,869616,869618," + \ 2158 "869620,869625,869627,869630,869633,869639,869641-869643,869645-" + \ 2159 "869652,869655,869657,869665,869668,869674,869677,869681,869685," + \ 2160 "869687-869688,869693,869697,869699-869700,869704-869708,869716," + \ 2161 "869719,869722,869724,869730,869733-869734,869737-869740,869745-" + \ 2162 "869746,869751-869754,869766,869812-869813,869815-869818,869820," + \ 2163 "869825,869837,869841,869843-869844,869858,869860-869861,869871," + \ 2164 "869875,869889,869895,869898,869902,869907,869909,869926,869928-" + \ 2165 "869929,869931-869933,869942-869943,869950,869952,869957-869958," + \ 2166 "869969,869972,869974,869988,869994,869996,869999,870004,870013-" + \ 2167 "870014,870016,870024,870032,870036,870039,870041-870043,870054," + \ 2168 "870060,870068-870071,870078,870083,870094,870104,870124,870127-" + \ 2169 "870128,870133,870135-870136,870141,870144,870148,870160,870172," + \ 2170 "870175,870191,870198,870203-870204,870211,870219,870225,870233," + \ 2171 "870235-870236,870254-870255,870259,870307,870311,870313,870320," + \ 2172 "870323,870330-870331,870352-870353,870355,870359-870360,870371," + \ 2173 "870373,870378,870393-870395,870402,870409-870410,870414,870416," + \ 2174 "870421,870436,870442,870447,870449,870452,870454,870466,870476," + \ 2175 "870481-870483,870486,870500,870502,870505,870513-870518,870522-" + \ 2176 "870523,870527,870529,870534,870536-870538,870540-870541,870543-" + \ 2177 "870548,870554,870556,870561,870563,870584,870590-870592,870594-" + \ 2178 "870595,870597,870618,870620,870622,870625-870626,870641,870647," + \ 2179 "870657,870665,870671,870681,870702-870703,870706-870708,870717-" + \ 2180 "870718,870727,870730,870737,870740,870742,870752,870758,870800," + \ 2181 "870809,870815,870817,870820-870825,870830,870834-870836,870850-" + \ 2182 "870851,870853,870859,870861,870886,870894,870916-870918,870942," + \ 2183 "870945,870957,870962,870970,870979,870981,870989,870996,871003," + \ 2184 "871005,871009,871011,871023,871033,871035-871038,871041,871060," + \ 2185 "871078,871080,871092,871097,871099,871105,871107,871120,871123-" + \ 2186 "871127,871130,871133-871135,871140,871149,871155-871156,871160," + \ 2187 "871162,871164,871181,871191,871199-871200,871205,871211-871212," + \ 2188 "871215,871219,871225,871227,871229,871231,871236,871270,871273," + \ 2189 "871277,871283,871297,871302,871306,871308,871315-871320,871323-" + \ 2190 "871325,871333-871335,871345,871347-871350,871354,871357,871361," + \ 2191 "871363-871366,871374-871375,871377,871382,871385-871388,871391," + \ 2192 "871408,871411,871422,871435,871441,871443-871444,871465,871470," + \ 2193 "871472-871476,871481,871489,871499,871501-871502,871505,871508," + \ 2194 "871520,871523,871525-871527,871538,871542,871544,871547-871549," + \ 2195 "871556,871559,871562-871563,871578,871581,871587,871589-871597," + \ 2196 "871608,871613,871616-871617,871620,871624,871649,871668,871675," + \ 2197 "871677,871693-871694,871696,871704,871732-871733,871744,871747," + \ 2198 "871759,871762,871766,871769,871793,871796,871799,871801,871811," + \ 2199 "871813,871821-871826,871831,871843,871860,871880,871891,871894," + \ 2200 "871899,871907,871911,871926,871928,871933,871935,871941-871942," + \ 2201 "871947-871949,871958,871974,872000-872001,872003,872005,872018," + \ 2202 "872022,872038,872065,872068,872086,872091,872093,872097,872103," + \ 2203 "872112,872130,872154,872157,872206,872216,872218-872219,872227," + \ 2204 "872234,872238,872243,872253,872255,872259,872261,872278-872279," + \ 2205 "872281,872310-872311,872362,872404,872416-872417,872429,872431," + \ 2206 "872434,872439,872450-872453,872468,872470,872477-872478,872483," + \ 2207 "872490-872491,872495,872515-872516,872518-872519,872537,872541," + \ 2208 "872544,872565,872568,872571-872573,872584,872596-872597,872612," + \ 2209 "872619,872624,872632,872656,872670,872706,872710,872713,872717," + \ 2210 "872746-872748,872777,872780-872782,872791,872804,872813,872845," + \ 2211 "872864,872870,872872,872947-872948,872961,872974,872981,872985-" + \ 2212 "872987,873004,873042,873049,873051,873076,873087,873090,873096," + \ 2213 "873098,873100,873183,873186,873192,873195,873210-873211,873247," + \ 2214 "873252,873256,873259,873275,873286,873288,873343,873379-873381," + \ 2215 "873443,873521,873538-873539,873714-873715,873718,873733,873745," + \ 2216 "873751,873767,873778,873781,873849,873856,873862,873914,873940," + \ 2217 "873947-873948,873975-873976,873987,873998,874026-874027,874075," + \ 2218 "874077-874078,874124-874125,874127,874156,874159,874161,874165," + \ 2219 "874168,874170,874184,874189,874204,874223-874224,874245,874258," + \ 2220 "874262,874270,874292-874297,874300-874301,874303,874305,874316-" + \ 2221 "874318,874330,874363,874380,874405,874421,874441,874459,874467," + \ 2222 "874473,874497,874506,874545-874546,874561,874566,874568,874580," + \ 2223 "874619,874621,874634,874636,874659,874673,874681,874727,874730," + \ 2224 "874743,874765-874767,874806,874816,874848,874868,874888,874896," + \ 2225 "874909,874912,874996,875051,875069,875129,875132,875134,875137," + \ 2226 "875151-875153,875186-875188,875190,875235-875237,875242-875243," + \ 2227 "875249,875388,875393,875406,875411\n" 2228 2229 # Set the 'big' mergeinfo prop on A/B, A/C, and A/D. 2230 svntest.main.file_write(prop_val_file, big_prop_val) 2231 2232 svntest.actions.run_and_verify_svn(None, [], 'propset', 2233 SVN_PROP_MERGEINFO, '-F', prop_val_file, 2234 B_path) 2235 svntest.actions.run_and_verify_svn(None, [], 'propset', 2236 SVN_PROP_MERGEINFO, '-F', prop_val_file, 2237 C_path) 2238 svntest.actions.run_and_verify_svn(None, [], 'propset', 2239 SVN_PROP_MERGEINFO, '-F', prop_val_file, 2240 D_path) 2241 svntest.actions.run_and_verify_svn(None, [], 'ci', '-m', 2242 'ps some large svn:mergeinfos', wc_dir) 2243 2244 # Run propget -vR svn:mergeinfo, redirecting the stdout to a file. 2245 arglist = [svntest.main.svn_binary, 'propget', SVN_PROP_MERGEINFO, '-vR', 2246 '--config-dir', svntest.main.default_config_dir, wc_dir] 2247 redir_file = open(redirect_file, 'wb') 2248 pg_proc = subprocess.Popen(arglist, stdout=redir_file) 2249 pg_proc.wait() 2250 redir_file.close() 2251 pg_stdout_redir = open(redirect_file, 'r').readlines() 2252 2253 # Check if the redirected output of svn pg -vR on the root of the WC 2254 # is what we expect. 2255 expected_mergeinfo_displayed = [ 2256 ' /' + line for line in big_prop_val.splitlines(True) ] 2257 expected_output = [ 2258 "Properties on '" + B_path + "':\n", # Should ocur only once! 2259 " svn:mergeinfo\n", 2260 ] + expected_mergeinfo_displayed + [ 2261 "Properties on '" + C_path + "':\n", # Should ocur only once! 2262 " svn:mergeinfo\n", 2263 ] + expected_mergeinfo_displayed + [ 2264 "Properties on '" + D_path + "':\n", # Should ocur only once! 2265 " svn:mergeinfo\n", 2266 ] + expected_mergeinfo_displayed 2267 svntest.verify.verify_outputs( 2268 "Redirected pg -vR doesn't match pg -vR stdout", 2269 pg_stdout_redir, None, 2270 svntest.verify.UnorderedOutput(expected_output), None) 2271 # (We want this check to fail if the redirected pg output contains 2272 # unexpected duplicate lines, although this hasn't been observed as 2273 # part of issue #3721. We used to check separately here because the old 2274 # UnorderedOutput class ignored duplicates but now it detects them.) 2275 2276@Issue(3852) 2277def file_matching_dir_prop_reject(sbox): 2278 "prop conflict for file matching dir prop reject" 2279 2280 sbox.build() 2281 wc_dir = sbox.wc_dir 2282 2283 # Add file with awkward name 2284 svntest.main.file_append(sbox.ospath('A/dir_conflicts'), "some content\n") 2285 svntest.actions.run_and_verify_svn(None, [], 2286 'add', sbox.ospath('A/dir_conflicts')) 2287 sbox.simple_propset('prop', 'val1', 'A/dir_conflicts') 2288 sbox.simple_propset('prop', 'val1', 'A') 2289 expected_output = svntest.wc.State(wc_dir, { 2290 'A' : Item(verb='Sending'), 2291 'A/dir_conflicts' : Item(verb='Adding'), 2292 }) 2293 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 2294 expected_status.tweak('A', wc_rev=2) 2295 expected_status.add({ 2296 'A/dir_conflicts' : Item(status=' ', wc_rev=2), 2297 }) 2298 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 2299 expected_status) 2300 2301 # Modify/commit property change 2302 sbox.simple_propset('prop', 'val2', 'A/dir_conflicts') 2303 sbox.simple_propset('prop', 'val2', 'A') 2304 expected_output = svntest.wc.State(wc_dir, { 2305 'A' : Item(verb='Sending'), 2306 'A/dir_conflicts' : Item(verb='Sending'), 2307 }) 2308 expected_status.tweak('A', 'A/dir_conflicts', wc_rev=3) 2309 svntest.actions.run_and_verify_commit(wc_dir, expected_output, 2310 expected_status) 2311 2312 # Local property mod 2313 sbox.simple_propset('prop', 'val3', 'A/dir_conflicts') 2314 sbox.simple_propset('prop', 'val3', 'A') 2315 2316 # Update to trigger property conflicts 2317 expected_disk = svntest.main.greek_state.copy() 2318 expected_disk.add({ 2319 'A/dir_conflicts' : Item('some content\n', props = {'prop' : 'val3'}), 2320 }) 2321 expected_disk.tweak('A', props={'prop' : 'val3'}) 2322 expected_output = svntest.wc.State(wc_dir, { 2323 'A' : Item(status=' C'), 2324 'A/dir_conflicts' : Item(status=' C'), 2325 }) 2326 expected_status.tweak(wc_rev=2) 2327 expected_status.tweak('A', 'A/dir_conflicts', status=' C') 2328 2329 # Conflict: BASE=val2 WORKING=val3 INCOMING_OLD=val2 INCOMING_NEW=val1 2330 extra_files = ['dir_conflicts.prej', 'dir_conflicts.2.prej'] 2331 svntest.actions.run_and_verify_update(wc_dir, 2332 expected_output, 2333 expected_disk, 2334 expected_status, 2335 [], True, 2336 '-r', '2', wc_dir, 2337 extra_files=extra_files) 2338 2339 # Revert and update to check that conflict files are removed 2340 svntest.actions.run_and_verify_svn(None, [], 'revert', '-R', wc_dir) 2341 expected_status.tweak('A', 'A/dir_conflicts', status=' ') 2342 svntest.actions.run_and_verify_status(wc_dir, expected_status) 2343 2344 expected_output = svntest.wc.State(wc_dir, { 2345 'A' : Item(status=' U'), 2346 'A/dir_conflicts' : Item(status=' U'), 2347 }) 2348 expected_disk.tweak('A', 'A/dir_conflicts', props={'prop' : 'val2'}) 2349 expected_status.tweak(wc_rev=3) 2350 svntest.actions.run_and_verify_update(wc_dir, 2351 expected_output, 2352 expected_disk, 2353 expected_status, 2354 check_props=True) 2355 2356def pristine_props_listed(sbox): 2357 "check if pristine properties are visible" 2358 2359 sbox.build() 2360 wc_dir = sbox.wc_dir 2361 2362 sbox.simple_propset('prop', 'val', 'A') 2363 sbox.simple_commit() 2364 2365 expected_output = ["Properties on '" + sbox.ospath('A') + "':\n", " prop\n"] 2366 2367 # Now we see the pristine properties 2368 svntest.actions.run_and_verify_svn(expected_output, [], 2369 'proplist', '-R', wc_dir, '-r', 'BASE') 2370 2371 sbox.simple_propset('prop', 'needs-fix', 'A') 2372 2373 # And now we see no property at all 2374 svntest.actions.run_and_verify_svn(expected_output, [], 2375 'proplist', '-R', wc_dir, '-r', 'BASE') 2376 2377def create_inherited_ignores_config(sbox): 2378 "create config stuffs for inherited ignores tests" 2379 2380 # contents of the file 'config' 2381 config_contents = '''\ 2382[miscellany] 2383global-ignores = *.boo *.goo 2384''' 2385 2386 return sbox.create_config_dir(config_contents) 2387 2388def inheritable_ignores(sbox): 2389 "inheritable ignores with svn:ignores and config" 2390 2391 sbox.build() 2392 wc_dir = sbox.wc_dir 2393 2394 config_dir = create_inherited_ignores_config(sbox) 2395 2396 sbox.simple_propset(SVN_PROP_INHERITABLE_IGNORES, '*.doo', 'A/B') 2397 sbox.simple_propset(SVN_PROP_INHERITABLE_IGNORES, '*.moo', 'A/D') 2398 sbox.simple_propset('svn:ignore', '*.foo', 'A/B/E') 2399 sbox.simple_commit() 2400 2401 # Some directories and files that should always be added because they 2402 # don't match any applicable ignore patterns. 2403 X_dir_path = sbox.ospath('ADD-ME-DIR-X') 2404 Y_dir_path = sbox.ospath('A/ADD-ME-DIR-Y.doo') 2405 Z_dir_path = sbox.ospath('A/D/G/ADD-ME-DIR-Z.doo') 2406 os.mkdir(X_dir_path) 2407 os.mkdir(Y_dir_path) 2408 os.mkdir(Z_dir_path) 2409 2410 # Some directories and files that should be ignored when adding 2411 # because they match an ignore pattern (unless of course they are 2412 # the direct target of an add, which we always add). 2413 boo_dir_path = sbox.ospath('IGNORE-ME-DIR.boo') 2414 goo_dir_path = sbox.ospath('IGNORE-ME-DIR.boo/IGNORE-ME-DIR.goo') 2415 doo_dir_path = sbox.ospath('A/B/IGNORE-ME-DIR.doo') 2416 moo_dir_path = sbox.ospath('A/D/IGNORE-ME-DIR.moo') 2417 foo_dir_path = sbox.ospath('A/B/E/IGNORE-ME-DIR.foo') 2418 os.mkdir(boo_dir_path) 2419 os.mkdir(goo_dir_path) 2420 os.mkdir(doo_dir_path) 2421 os.mkdir(moo_dir_path) 2422 os.mkdir(foo_dir_path) 2423 boo_file_path = sbox.ospath('ADD-ME-DIR-X/ignore-me-file.boo') 2424 goo_file_path = sbox.ospath('A/D/G/ignore-me-file.goo') 2425 doo_file_path = sbox.ospath('A/B/IGNORE-ME-DIR.doo/ignore-me-file.doo') 2426 doo_file2_path = sbox.ospath('A/B/E/ignore-me-file.doo') 2427 moo_file_path = sbox.ospath('A/D/ignore-me-file.moo') 2428 foo_file_path = sbox.ospath('A/B/E/ignore-me-file.foo') 2429 svntest.main.file_write(boo_file_path, 'I should not be versioned!\n') 2430 svntest.main.file_write(goo_file_path, 'I should not be versioned!\n') 2431 svntest.main.file_write(doo_file_path, 'I should not be versioned!\n') 2432 svntest.main.file_write(doo_file2_path, 'I should not be versioned!\n') 2433 svntest.main.file_write(moo_file_path, 'I should not be versioned!\n') 2434 svntest.main.file_write(foo_file_path, 'I should not be versioned!\n') 2435 2436 # Some directories and files that don't match any ignore pattern 2437 # but are located within a subtree that does match and so shouldn't 2438 # be added. 2439 roo_file_path = sbox.ospath('A/B/IGNORE-ME-DIR.doo/ignore-me-file.roo') 2440 svntest.main.file_write(roo_file_path, 'I should not be versioned!\n') 2441 2442 # Check (non-verbose) status with the custom config. We should only see 2443 # the three unversioned directories which don't match any of the ignore 2444 # patterns and aren't proper subtrees of an unversioned or ignored 2445 # subtree. 2446 expected_output = svntest.verify.UnorderedOutput( 2447 ['? ' + X_dir_path + '\n', 2448 '? ' + Y_dir_path + '\n', 2449 '? ' + Z_dir_path + '\n',]) 2450 svntest.actions.run_and_verify_svn(expected_output, [], 'st', 2451 '--config-dir', config_dir, wc_dir) 2452 2453 # Check status without the custom config. 2454 # Should be the same as above except the *.boo and *.goo paths 2455 # now show up as unversioned '?'. 2456 expected_output = svntest.verify.UnorderedOutput( 2457 ['? ' + X_dir_path + '\n', 2458 '? ' + Y_dir_path + '\n', 2459 '? ' + Z_dir_path + '\n', 2460 '? ' + boo_dir_path + '\n', 2461 '? ' + goo_file_path + '\n',]) 2462 svntest.actions.run_and_verify_svn(expected_output, [], 'st', wc_dir) 2463 2464 # Check status with the custom config and --no-ignore. 2465 expected_output = svntest.verify.UnorderedOutput( 2466 ['? ' + X_dir_path + '\n', 2467 '? ' + Y_dir_path + '\n', 2468 '? ' + Z_dir_path + '\n', 2469 'I ' + boo_dir_path + '\n', 2470 'I ' + doo_dir_path + '\n', 2471 'I ' + doo_file2_path + '\n', 2472 'I ' + moo_dir_path + '\n', 2473 'I ' + foo_dir_path + '\n', 2474 'I ' + goo_file_path + '\n', 2475 'I ' + moo_file_path + '\n', 2476 'I ' + foo_file_path + '\n',]) 2477 svntest.actions.run_and_verify_svn(expected_output, [], 'st', 2478 '--config-dir', config_dir, 2479 '--no-ignore', wc_dir) 2480 2481 # Check status without the custom config and --no-ignore. 2482 # Should be the same as above except the *.boo and *.goo paths 2483 # are reported as unversioned '?' rather than ignored 'I'. 2484 expected_output = svntest.verify.UnorderedOutput( 2485 ['? ' + X_dir_path + '\n', 2486 '? ' + Y_dir_path + '\n', 2487 '? ' + Z_dir_path + '\n', 2488 '? ' + boo_dir_path + '\n', 2489 'I ' + doo_dir_path + '\n', 2490 'I ' + doo_file2_path + '\n', 2491 'I ' + moo_dir_path + '\n', 2492 'I ' + foo_dir_path + '\n', 2493 '? ' + goo_file_path + '\n', 2494 'I ' + moo_file_path + '\n', 2495 'I ' + foo_file_path + '\n',]) 2496 svntest.actions.run_and_verify_svn(expected_output, [], 'st', 2497 '--no-ignore', wc_dir) 2498 2499 # Perform the add with the --force flag, targeting the root of the WC. 2500 ### Note: You have to be inside the working copy or else Subversion 2501 ### will think you're trying to add the working copy to its parent 2502 ### directory, and will (possibly, if the parent directory isn't 2503 ### versioned) fail -- see also schedule_tests.py 11 "'svn add' 2504 ### should traverse already-versioned dirs" 2505 saved_wd = os.getcwd() 2506 os.chdir(sbox.wc_dir) 2507 expected = svntest.verify.UnorderedOutput( 2508 ['A ' + 'ADD-ME-DIR-X\n', 2509 'A ' + os.path.join('A', 'ADD-ME-DIR-Y.doo') + '\n', 2510 'A ' + os.path.join('A', 'D', 'G', 'ADD-ME-DIR-Z.doo') + '\n']) 2511 svntest.actions.run_and_verify_svn(expected, 2512 [], 'add', '.', '--force', 2513 '--config-dir', config_dir) 2514 os.chdir(saved_wd) 2515 2516 # Now revert and try the add with the --no-ignore flag, nothing should 2517 # be ignored. 2518 svntest.actions.run_and_verify_svn(None, [], 'revert', wc_dir, '-R') 2519 saved_wd = os.getcwd() 2520 os.chdir(sbox.wc_dir) 2521 expected = svntest.verify.UnorderedOutput( 2522 ['A ' + 'ADD-ME-DIR-X\n', 2523 'A ' + os.path.join('A', 'ADD-ME-DIR-Y.doo') + '\n', 2524 'A ' + os.path.join('A', 'D', 'G', 'ADD-ME-DIR-Z.doo') + '\n', 2525 'A ' + os.path.join('ADD-ME-DIR-X', 'ignore-me-file.boo') + '\n', 2526 'A ' + 'IGNORE-ME-DIR.boo' + '\n', 2527 'A ' + os.path.join('IGNORE-ME-DIR.boo', 2528 'IGNORE-ME-DIR.goo') + '\n', 2529 'A ' + os.path.join('A', 'B', 'E', 'IGNORE-ME-DIR.foo') + '\n', 2530 'A ' + os.path.join('A', 'B', 'E', 'ignore-me-file.foo') + '\n', 2531 'A ' + os.path.join('A', 'D', 'G', 'ignore-me-file.goo') + '\n', 2532 2533 'A ' + os.path.join('A', 'B', 'E', 'ignore-me-file.doo') + '\n', 2534 'A ' + os.path.join('A', 'B', 'IGNORE-ME-DIR.doo') + '\n', 2535 'A ' + os.path.join('A', 'B', 'IGNORE-ME-DIR.doo', 2536 'ignore-me-file.doo') + '\n', 2537 'A ' + os.path.join('A', 'B', 'IGNORE-ME-DIR.doo', 2538 'ignore-me-file.roo') + '\n', 2539 'A ' + os.path.join('A', 'D', 'IGNORE-ME-DIR.moo') + '\n', 2540 'A ' + os.path.join('A', 'D', 'ignore-me-file.moo') + '\n']) 2541 svntest.actions.run_and_verify_svn(expected, [], 'add', '.', '--force', 2542 '--no-ignore', '--config-dir', 2543 config_dir) 2544 2545def almost_known_prop_names(sbox): 2546 "propset with svn: prefix but unknown name" 2547 2548 sbox.build(read_only=True) 2549 wc_dir = sbox.wc_dir 2550 iota_path = sbox.ospath('iota') 2551 2552 # Same prefix, different prop name 2553 svntest.actions.set_prop('svn:exemutable', 'x', iota_path, 2554 "svn: E195011: 'svn:exemutable' " 2555 "is not a valid svn: property name") 2556 svntest.actions.set_prop('svn:exemutable', 'x', iota_path, force=True) 2557 2558 # Similar prefix, different prop name 2559 svntest.actions.set_prop('svm:exemutable', 'x', iota_path) 2560 2561 # Similar prefix, same prop name 2562 svntest.actions.set_prop('svm:executable', 'x', iota_path, 2563 "svn: E195011: 'svm:executable' " 2564 "is not a valid svn: property name") 2565 svntest.actions.set_prop('svm:executable', 'x', iota_path, force=True) 2566 2567 # Different prefix, same prop name 2568 svntest.actions.set_prop('tsvn:executable', 'x', iota_path) 2569 2570 # Property name is too different to matter 2571 svntest.actions.set_prop('svn:foobar', 'x', iota_path, 2572 "svn: E195011: 'svn:foobar'" 2573 " is not a valid svn: property name;" 2574 " use '--force' to set it") 2575 2576@Issue(3231) 2577def peg_rev_base_working(sbox): 2578 """peg rev @BASE, peg rev @WORKING""" 2579 2580 sbox.build() 2581 wc_dir = sbox.wc_dir 2582 2583 # set up a local prop mod 2584 svntest.actions.set_prop('ordinal', 'ninth\n', sbox.ospath('iota')) 2585 sbox.simple_commit(message='r2') 2586 svntest.actions.set_prop('cardinal', 'nine\n', sbox.ospath('iota')) 2587 svntest.actions.run_and_verify_svn(['ninth\n'], [], 2588 'propget', '--no-newline', 'ordinal', 2589 sbox.ospath('iota') + '@BASE') 2590 2591@Issue(4415) 2592def xml_unsafe_author(sbox): 2593 "svn:author with XML unsafe chars" 2594 2595 sbox.build() 2596 wc_dir = sbox.wc_dir 2597 2598 svntest.actions.enable_revprop_changes(sbox.repo_dir) 2599 2600 # client sends svn:author (via PROPPATCH for DAV) 2601 svntest.actions.run_and_verify_svn(None, [], 2602 'propset', '--revprop', '-r', '1', 2603 'svn:author', 'foo\bbar', wc_dir) 2604 2605 # mod_dav_svn sends svn:author (via REPORT for DAV) 2606 sbox.simple_update(revision=0) 2607 sbox.simple_update(revision=1) 2608 expected_info = [{ 2609 'Path' : re.escape(wc_dir), 2610 'Repository Root' : sbox.repo_url, 2611 'Repository UUID' : svntest.actions.get_wc_uuid(wc_dir), 2612 'Last Changed Author' : 'foo\bbar', 2613 }] 2614 svntest.actions.run_and_verify_info(expected_info, wc_dir) 2615 2616 # mod_dav_svn sends svn:author (via PROPFIND for DAV) 2617 # Since r1553367 this works correctly on ra_serf, since we now request 2618 # a single property value which skips creating the creator-displayname property 2619 svntest.actions.run_and_verify_svn(['foo\bbar'], [], 2620 'propget', '--revprop', '-r', '1', 2621 'svn:author', '--no-newline', wc_dir) 2622 2623 # Ensure a stable date 2624 svntest.actions.run_and_verify_svn(None, [], 2625 'propset', '--revprop', '-r', '1', 2626 'svn:date', '2015-01-01T00:00:00.0Z', wc_dir) 2627 2628 # But a proplist of this property value still fails via DAV. 2629 expected_output = svntest.verify.UnorderedOutput([ 2630 'Unversioned properties on revision 1:\n', 2631 ' svn:author\n', 2632 ' foo\bbar\n', 2633 ' svn:date\n', 2634 ' 2015-01-01T00:00:00.0Z\n', 2635 ' svn:log\n', 2636 ' Log message for revision 1.\n' 2637 ]) 2638 svntest.actions.run_and_verify_svn(expected_output, [], 2639 'proplist', '--revprop', '-r', '1', '-v', 2640 wc_dir) 2641 2642@Issue(4415) 2643def xml_unsafe_author2(sbox): 2644 "svn:author with XML unsafe chars 2" 2645 2646 sbox.build(create_wc = False) 2647 repo_url = sbox.repo_url 2648 2649 svntest.actions.enable_revprop_changes(sbox.repo_dir) 2650 2651 # client sends svn:author (via PROPPATCH for DAV) 2652 svntest.actions.run_and_verify_svn(None, [], 2653 'propset', '--revprop', '-r', '1', 2654 'svn:author', 'foo\bbar', repo_url) 2655 2656 # Ensure a stable date 2657 svntest.actions.run_and_verify_svn(None, [], 2658 'propset', '--revprop', '-r', '1', 2659 'svn:date', '2000-01-01T12:00:00.0Z', 2660 repo_url) 2661 2662 if svntest.main.is_ra_type_dav(): 2663 # This receives the filtered author (but that is better than an Xml fail) 2664 expected_author = 'foobar' 2665 else: 2666 expected_author = 'foo\bbar' 2667 2668 # Use svn ls in --xml mode to test locale independent output. 2669 expected_output = [ 2670 '<?xml version="1.0" encoding="UTF-8"?>\n', 2671 '<lists>\n', 2672 '<list\n', 2673 ' path="%s">\n' % sbox.repo_url, 2674 '<entry\n', 2675 ' kind="dir">\n', 2676 '<name>A</name>\n', 2677 '<commit\n', 2678 ' revision="1">\n', 2679 '<author>%s</author>\n' % expected_author, 2680 '<date>2000-01-01T12:00:00.000000Z</date>\n', 2681 '</commit>\n', 2682 '</entry>\n', 2683 '<entry\n', 2684 ' kind="file">\n', 2685 '<name>iota</name>\n', 2686 '<size>25</size>\n', 2687 '<commit\n', 2688 ' revision="1">\n', 2689 '<author>%s</author>\n' % expected_author, 2690 '<date>2000-01-01T12:00:00.000000Z</date>\n', 2691 '</commit>\n', 2692 '</entry>\n', 2693 '</list>\n', 2694 '</lists>\n' 2695 ] 2696 2697 svntest.actions.run_and_verify_svn(expected_output, [], 2698 'ls', '--xml', repo_url) 2699 2700 expected_info = [{ 2701 'Repository Root' : sbox.repo_url, 2702 'Last Changed Author' : expected_author, 2703 }] 2704 svntest.actions.run_and_verify_info(expected_info, repo_url) 2705 2706def dir_prop_conflict_details(sbox): 2707 "verify dir property conflict details" 2708 2709 sbox.build() 2710 wc_dir = sbox.wc_dir 2711 2712 # Apply some changes 2713 sbox.simple_propset('svn:mergeinfo', '/B:1', 'A') 2714 sbox.simple_propset('my-prop', 'my-val', 'A') 2715 sbox.simple_commit() 2716 2717 # Revert to r1 2718 sbox.simple_update('', revision=1) 2719 2720 # Apply some incompatible changes 2721 sbox.simple_propset('svn:mergeinfo', '/C:1', 'A') 2722 sbox.simple_propset('my-prop', 'other-val', 'A') 2723 2724 # This should report out of date because there are incompatible property 2725 # changes that can't be merged on the server 2726 svntest.actions.run_and_verify_commit(wc_dir, 2727 None, 2728 None, 2729 '.*[Oo]ut of date.*') 2730 2731 expected_output = svntest.wc.State(wc_dir, { 2732 'A' : Item(status=' C'), 2733 }) 2734 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 2735 expected_status.tweak('A', status=' C') 2736 2737 svntest.actions.run_and_verify_update(wc_dir, 2738 expected_output, 2739 None, 2740 expected_status, 2741 check_props=True) 2742 expected_info = { 2743 'Conflicted Properties' : 'my-prop', 2744 'Conflict Details': re.escape('incoming dir edit upon update' 2745 + ' Source left: (dir) ^/A@1' 2746 + ' Source right: (dir) ^/A@2') 2747 } 2748 svntest.actions.run_and_verify_info([expected_info], sbox.path('A')) 2749 2750 2751def iprops_list_abspath(sbox): 2752 "test listing iprops via abspath" 2753 2754 sbox.build() 2755 2756 sbox.simple_propset('im', 'root', '') 2757 sbox.simple_commit() 2758 2759 svntest.actions.run_and_verify_svn(None, [], 2760 'switch', '^/A/D', sbox.ospath(''), 2761 '--ignore-ancestry') 2762 2763 sbox.simple_propset('im', 'GammA', 'gamma') 2764 2765 expected_output = [ 2766 'Inherited properties on \'%s\',\n' % sbox.ospath(''), 2767 'from \'%s\':\n' % sbox.repo_url, 2768 ' im\n', 2769 ' root\n', 2770 'Properties on \'%s\':\n' % sbox.ospath('gamma'), 2771 ' im\n', 2772 ' GammA\n' 2773 ] 2774 svntest.actions.run_and_verify_svn(expected_output, [], 2775 'pl', '-R', 2776 '--show-inherited-props', '-v', 2777 sbox.ospath('')) 2778 2779 expected_output = [ 2780 'Inherited properties on \'%s\',\n' % os.path.abspath(sbox.ospath('')), 2781 'from \'%s\':\n' % sbox.repo_url, 2782 ' im\n', 2783 ' root\n', 2784 'Properties on \'%s\':\n' % os.path.abspath(sbox.ospath('gamma')), 2785 ' im\n', 2786 ' GammA\n' 2787 ] 2788 svntest.actions.run_and_verify_svn(expected_output, [], 2789 'pl', '-R', 2790 '--show-inherited-props', '-v', 2791 os.path.abspath(sbox.ospath(''))) 2792 2793def wc_propop_on_url(sbox): 2794 "perform wc specific operations on url" 2795 2796 sbox.build(create_wc = False) 2797 2798 svntest.actions.run_and_verify_svn(None, '.*E195000:.*path', 2799 'pl', '-r', 'PREV', 2800 sbox.repo_url) 2801 2802 svntest.actions.run_and_verify_svn(None, '.*E195000:.*path', 2803 'pg', 'my:Q', '-r', 'PREV', 2804 sbox.repo_url) 2805 2806def prop_conflict_root(sbox): 2807 """property conflict on wc root""" 2808 2809 sbox.build() 2810 wc_dir = sbox.wc_dir 2811 2812 sbox.simple_propset('propname', 'propval1', '') 2813 sbox.simple_commit() 2814 sbox.simple_propset('propname', 'propval2', '') 2815 sbox.simple_commit() 2816 sbox.simple_update(revision=2) 2817 sbox.simple_propset('propname', 'propvalconflict', '') 2818 2819 expected_output = svntest.wc.State(wc_dir, { 2820 '' : Item(status=' C'), 2821 }) 2822 expected_disk = svntest.main.greek_state.copy() 2823 expected_status = svntest.actions.get_virginal_state(wc_dir, 3) 2824 expected_status.tweak('', status=' C') 2825 extra_files = ['dir_conflicts.prej'] 2826 svntest.actions.run_and_verify_update(wc_dir, 2827 expected_output, 2828 expected_disk, 2829 expected_status, 2830 extra_files=extra_files) 2831 2832######################################################################## 2833# Run the tests 2834 2835# list all tests here, starting with None: 2836test_list = [ None, 2837 make_local_props, 2838 commit_props, 2839 update_props, 2840 downdate_props, 2841 remove_props, 2842 update_conflict_props, 2843 commit_conflict_dirprops, 2844 commit_replacement_props, 2845 revert_replacement_props, 2846 inappropriate_props, 2847 copy_inherits_special_props, 2848 revprop_change, 2849 prop_value_conversions, 2850 binary_props, 2851 recursive_base_wc_ops, 2852 url_props_ops, 2853 removal_schedule_added_props, 2854 update_props_on_wc_root, 2855 props_on_replaced_file, 2856 depthy_wc_proplist, 2857 depthy_url_proplist, 2858 invalid_propnames, 2859 perms_on_symlink, 2860 remove_custom_ns_props, 2861 props_over_time, 2862 invalid_propvalues, 2863 same_replacement_props, 2864 added_moved_file, 2865 delete_nonexistent_property, 2866 post_revprop_change_hook, 2867 rm_of_replaced_file, 2868 prop_reject_grind, 2869 obstructed_subdirs, 2870 atomic_over_ra, 2871 propget_redirection, 2872 file_matching_dir_prop_reject, 2873 pristine_props_listed, 2874 inheritable_ignores, 2875 almost_known_prop_names, 2876 peg_rev_base_working, 2877 xml_unsafe_author, 2878 xml_unsafe_author2, 2879 dir_prop_conflict_details, 2880 iprops_list_abspath, 2881 wc_propop_on_url, 2882 prop_conflict_root, 2883 ] 2884 2885if __name__ == '__main__': 2886 svntest.main.run_tests(test_list) 2887 # NOTREACHED 2888 2889 2890### End of file. 2891