1#!/usr/bin/env python 2# 3# changelist_tests.py: testing changelist uses. 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 string, sys, os, re 29 30# Our testing module 31import svntest 32 33# (abbreviation) 34Skip = svntest.testcase.Skip_deco 35SkipUnless = svntest.testcase.SkipUnless_deco 36XFail = svntest.testcase.XFail_deco 37Issues = svntest.testcase.Issues_deco 38Issue = svntest.testcase.Issue_deco 39Wimp = svntest.testcase.Wimp_deco 40Item = svntest.wc.StateItem 41 42 43###################################################################### 44# Utilities 45 46 47def mod_all_files(wc_dir, new_text): 48 """Walk over working copy WC_DIR, appending NEW_TEXT to all the 49 files in that tree (but not inside the .svn areas of that tree).""" 50 51 dot_svn = svntest.main.get_admin_name() 52 for dirpath, dirs, files in os.walk(wc_dir): 53 if dot_svn in dirs: 54 dirs.remove(dot_svn) 55 for name in files: 56 svntest.main.file_append(os.path.join(dirpath, name), new_text) 57 58def changelist_all_files(wc_dir, name_func): 59 """Walk over working copy WC_DIR, adding versioned files to 60 changelists named by invoking NAME_FUNC(full-path-of-file) and 61 noting its string return value (or None, if we wish to remove the 62 file from a changelist).""" 63 64 dot_svn = svntest.main.get_admin_name() 65 for dirpath, dirs, files in os.walk(wc_dir): 66 if dot_svn in dirs: 67 dirs.remove(dot_svn) 68 for name in files: 69 full_path = os.path.join(dirpath, name) 70 clname = name_func(full_path) 71 if not clname: 72 svntest.main.run_svn(None, "changelist", "--remove", full_path) 73 else: 74 svntest.main.run_svn(None, "changelist", clname, full_path) 75 76def select_paths(target_path, depth, changelists, name_func): 77 """Return the subset of paths found on disk at TARGET_PATH, to a depth 78 of DEPTH, that match CHANGELISTS. 79 NAME_FUNC, rather than the working copy, determines what 80 changelist each path is associated with. 81 Returned paths are relative to the CWD. 82 83 ### Only the paths of files are returned. 84 """ 85 dot_svn = svntest.main.get_admin_name() 86 for dirpath, dirs, files in os.walk(target_path): 87 # prepare to return paths relative to WC_DIR 88 if dot_svn in dirs: 89 dirs.remove(dot_svn) 90 if not changelists: # When changelists support dirs, add: "or name_func(name) in changelists" 91 yield os.path.normpath(dirpath) 92 if depth == 'empty': 93 dirs[:] = [] # process no subdirs 94 continue # nor files 95 for name in files: 96 if not changelists or name_func(name) in changelists: 97 yield os.path.normpath(os.path.join(dirpath, name)) 98 if depth == 'files': 99 dirs[:] = [] # process no subdirs 100 if depth == 'immediates': 101 depth = 'empty' # process subdirs, but no files nor dirs in them 102 103def clname_from_lastchar_cb(full_path): 104 """Callback for changelist_all_files() that returns a changelist 105 name matching the last character in the file's name. For example, 106 after running this on a greek tree where every file has some text 107 modification, 'svn status' shows: 108 109 --- Changelist 'a': 110 M A/B/lambda 111 M A/B/E/alpha 112 M A/B/E/beta 113 M A/D/gamma 114 M A/D/H/omega 115 M iota 116 117 --- Changelist 'u': 118 M A/mu 119 M A/D/G/tau 120 121 --- Changelist 'i': 122 M A/D/G/pi 123 M A/D/H/chi 124 M A/D/H/psi 125 126 --- Changelist 'o': 127 M A/D/G/rho 128 """ 129 return full_path[-1] 130 131 132# Regular expressions for 'svn changelist' output. 133_re_cl_rem_pattern = "^D \[(.*)\] (.*)" 134_re_cl_skip = re.compile("Skipped '(.*)'") 135_re_cl_add = re.compile("^A \[(.*)\] (.*)") 136_re_cl_rem = re.compile(_re_cl_rem_pattern) 137 138def verify_changelist_output(output, expected_adds=None, 139 expected_removals=None, 140 expected_skips=None): 141 """Compare lines of OUTPUT from 'svn changelist' against 142 EXPECTED_ADDS (a dictionary mapping paths to changelist names), 143 EXPECTED_REMOVALS (a dictionary mapping paths to ... whatever), and 144 EXPECTED_SKIPS (a dictionary mapping paths to ... whatever). 145 146 EXPECTED_SKIPS is ignored if None.""" 147 148 num_expected = 0 149 if expected_adds: 150 num_expected += len(expected_adds) 151 if expected_removals: 152 num_expected += len(expected_removals) 153 if expected_skips: 154 num_expected += len(expected_skips) 155 156 if not expected_skips: 157 output = [line for line in output if (not _re_cl_skip.match(line))] 158 159 for line in output: 160 line = line.rstrip() 161 match = _re_cl_rem.match(line) 162 if match \ 163 and expected_removals \ 164 and match.group(2) in expected_removals: 165 continue 166 elif match: 167 raise svntest.Failure("Unexpected changelist removal line: " + line) 168 match = _re_cl_add.match(line) 169 if match \ 170 and expected_adds \ 171 and expected_adds.get(match.group(2)) == match.group(1): 172 continue 173 elif match: 174 raise svntest.Failure("Unexpected changelist add line: " + line) 175 match = _re_cl_skip.match(line) 176 if match \ 177 and expected_skips \ 178 and match.group(2) in expected_skips: 179 continue 180 elif match: 181 raise svntest.Failure("Unexpected changelist skip line: " + line) 182 raise svntest.Failure("Unexpected line: " + line) 183 184 if len(output) != num_expected: 185 raise svntest.Failure("Unexpected number of 'svn changelist' output " + 186 "lines (%d vs %d)" % (len(output), num_expected)) 187 188def verify_pget_output(output, expected_props): 189 """Compare lines of OUTPUT from 'svn propget' against EXPECTED_PROPS 190 (a dictionary mapping paths to property values).""" 191 192 _re_pget = re.compile('^(.*) - (.*)$') 193 actual_props = {} 194 for line in output: 195 try: 196 path, prop = line.rstrip().split(' - ') 197 except: 198 raise svntest.Failure("Unexpected output line: " + line) 199 actual_props[path] = prop 200 if expected_props != actual_props: 201 raise svntest.Failure("Got unexpected property results\n" 202 "\tExpected: %s\n" 203 "\tActual: %s" % (str(expected_props), 204 str(actual_props))) 205 206 207###################################################################### 208# Tests 209# 210# Each test must return on success or raise on failure. 211 212 213#---------------------------------------------------------------------- 214 215def add_remove_changelists(sbox): 216 "add and remove files from changelists" 217 218 sbox.build() 219 wc_dir = sbox.wc_dir 220 221 ### 'Skip' notifications 222 223 def expected_skips_under(*greek_path): 224 "return a dict mapping Greek-tree directories below GREEK_PATH to None" 225 226 expected_skips = {} 227 for path in expected_skips_all: 228 if path.startswith(os.path.join(wc_dir, *greek_path)): 229 expected_skips[path] = None 230 231 return expected_skips 232 233 def all_parents(expected_adds): 234 """return a dict mapping Greek-tree directories above directories in 235 EXPECTED_ADDS to None""" 236 237 expected_skips = {} 238 for path in expected_adds.keys(): 239 if not os.path.isdir(path): 240 path = os.path.dirname(path) 241 242 while path != wc_dir: 243 expected_skips[path] = None 244 path = os.path.dirname(path) 245 246 expected_skips[wc_dir] = None 247 return expected_skips 248 249 # all dirs in the Greek tree 250 expected_skips_all = dict([(x, None) for x in [ 251 sbox.ospath(''), 252 sbox.ospath('A'), 253 sbox.ospath('A/B'), 254 sbox.ospath('A/B/E'), 255 sbox.ospath('A/B/F'), 256 sbox.ospath('A/C'), 257 sbox.ospath('A/D'), 258 sbox.ospath('A/D/G'), 259 sbox.ospath('A/D/H'), 260 ]]) 261 262 expected_skips_wc_dir = { wc_dir : None } 263 264 ### First, we play with just adding to changelists ### 265 266 # svn changelist foo WC_DIR 267 exit_code, output, errput = svntest.main.run_svn(None, "changelist", "foo", 268 wc_dir) 269 verify_changelist_output(output) # nothing expected 270 271 # svn changelist foo WC_DIR --depth files 272 exit_code, output, errput = svntest.main.run_svn(None, "changelist", "foo", 273 "--depth", "files", 274 wc_dir) 275 expected_adds = { 276 os.path.join(wc_dir, 'iota') : 'foo', 277 } 278 verify_changelist_output(output, expected_adds) 279 280 # svn changelist foo WC_DIR --depth infinity 281 exit_code, output, errput = svntest.main.run_svn(None, "changelist", "foo", 282 "--depth", "infinity", 283 wc_dir) 284 expected_adds = { 285 sbox.ospath('A/B/E/alpha') : 'foo', 286 sbox.ospath('A/B/E/beta') : 'foo', 287 sbox.ospath('A/B/lambda') : 'foo', 288 sbox.ospath('A/D/G/pi') : 'foo', 289 sbox.ospath('A/D/G/rho') : 'foo', 290 sbox.ospath('A/D/G/tau') : 'foo', 291 sbox.ospath('A/D/H/chi') : 'foo', 292 sbox.ospath('A/D/H/omega') : 'foo', 293 sbox.ospath('A/D/H/psi') : 'foo', 294 sbox.ospath('A/D/gamma') : 'foo', 295 sbox.ospath('A/mu') : 'foo', 296 } 297 verify_changelist_output(output, expected_adds) 298 299 ### Now, change some changelists ### 300 301 # svn changelist bar WC_DIR/A/D --depth infinity 302 exit_code, output, errput = svntest.main.run_svn(".*", "changelist", "bar", 303 "--depth", "infinity", 304 sbox.ospath('A/D')) 305 expected_adds = { 306 sbox.ospath('A/D/G/pi') : 'bar', 307 sbox.ospath('A/D/G/rho') : 'bar', 308 sbox.ospath('A/D/G/tau') : 'bar', 309 sbox.ospath('A/D/H/chi') : 'bar', 310 sbox.ospath('A/D/H/omega') : 'bar', 311 sbox.ospath('A/D/H/psi') : 'bar', 312 sbox.ospath('A/D/gamma') : 'bar', 313 } 314 expected_removals = expected_adds 315 verify_changelist_output(output, expected_adds, expected_removals) 316 317 # svn changelist baz WC_DIR/A/D/H --depth infinity 318 exit_code, output, errput = svntest.main.run_svn(".*", "changelist", "baz", 319 "--depth", "infinity", 320 sbox.ospath('A/D/H')) 321 expected_adds = { 322 sbox.ospath('A/D/H/chi') : 'baz', 323 sbox.ospath('A/D/H/omega') : 'baz', 324 sbox.ospath('A/D/H/psi') : 'baz', 325 } 326 expected_removals = expected_adds 327 verify_changelist_output(output, expected_adds, expected_removals) 328 329 ### Now, let's selectively rename some changelists ### 330 331 # svn changelist foo-rename WC_DIR --depth infinity --changelist foo 332 exit_code, output, errput = svntest.main.run_svn(".*", "changelist", 333 "foo-rename", 334 "--depth", "infinity", 335 "--changelist", "foo", 336 wc_dir) 337 expected_adds = { 338 sbox.ospath('A/B/E/alpha') : 'foo-rename', 339 sbox.ospath('A/B/E/beta') : 'foo-rename', 340 sbox.ospath('A/B/lambda') : 'foo-rename', 341 sbox.ospath('A/mu') : 'foo-rename', 342 sbox.ospath('iota') : 'foo-rename', 343 } 344 expected_removals = expected_adds 345 verify_changelist_output(output, expected_adds, expected_removals) 346 347 # svn changelist bar WC_DIR --depth infinity 348 # --changelist foo-rename --changelist baz 349 exit_code, output, errput = svntest.main.run_svn( 350 ".*", "changelist", "bar", "--depth", "infinity", 351 "--changelist", "foo-rename", "--changelist", "baz", wc_dir) 352 353 expected_adds = { 354 sbox.ospath('A/B/E/alpha') : 'bar', 355 sbox.ospath('A/B/E/beta') : 'bar', 356 sbox.ospath('A/B/lambda') : 'bar', 357 sbox.ospath('A/D/H/chi') : 'bar', 358 sbox.ospath('A/D/H/omega') : 'bar', 359 sbox.ospath('A/D/H/psi') : 'bar', 360 sbox.ospath('A/mu') : 'bar', 361 sbox.ospath('iota') : 'bar', 362 } 363 expected_removals = expected_adds 364 verify_changelist_output(output, expected_adds, expected_removals) 365 366 ### Okay. Time to remove some stuff from changelists now. ### 367 368 # svn changelist --remove WC_DIR 369 exit_code, output, errput = svntest.main.run_svn(None, "changelist", 370 "--remove", wc_dir) 371 verify_changelist_output(output) # nothing expected 372 373 # svn changelist --remove WC_DIR --depth files 374 exit_code, output, errput = svntest.main.run_svn(None, "changelist", 375 "--remove", 376 "--depth", "files", 377 wc_dir) 378 expected_removals = { 379 os.path.join(wc_dir, 'iota') : None, 380 } 381 verify_changelist_output(output, None, expected_removals) 382 383 # svn changelist --remove WC_DIR --depth infinity 384 exit_code, output, errput = svntest.main.run_svn(None, "changelist", 385 "--remove", 386 "--depth", "infinity", 387 wc_dir) 388 expected_removals = { 389 sbox.ospath('A/B/E/alpha') : None, 390 sbox.ospath('A/B/E/beta') : None, 391 sbox.ospath('A/B/lambda') : None, 392 sbox.ospath('A/D/G/pi') : None, 393 sbox.ospath('A/D/G/rho') : None, 394 sbox.ospath('A/D/G/tau') : None, 395 sbox.ospath('A/D/H/chi') : None, 396 sbox.ospath('A/D/H/omega') : None, 397 sbox.ospath('A/D/H/psi') : None, 398 sbox.ospath('A/D/gamma') : None, 399 sbox.ospath('A/mu') : None, 400 } 401 verify_changelist_output(output, None, expected_removals) 402 403 ### Add files to changelists based on the last character in their names ### 404 405 changelist_all_files(wc_dir, clname_from_lastchar_cb) 406 407 ### Now, do selective changelist removal ### 408 409 # svn changelist --remove WC_DIR --depth infinity --changelist a 410 exit_code, output, errput = svntest.main.run_svn(None, "changelist", 411 "--remove", 412 "--depth", "infinity", 413 "--changelist", "a", 414 wc_dir) 415 expected_removals = { 416 sbox.ospath('A/B/E/alpha') : None, 417 sbox.ospath('A/B/E/beta') : None, 418 sbox.ospath('A/B/lambda') : None, 419 sbox.ospath('A/D/H/omega') : None, 420 sbox.ospath('A/D/gamma') : None, 421 sbox.ospath('iota') : None, 422 } 423 verify_changelist_output(output, None, expected_removals) 424 425 # svn changelist --remove WC_DIR --depth infinity 426 # --changelist i --changelist o 427 exit_code, output, errput = svntest.main.run_svn(None, "changelist", 428 "--remove", 429 "--depth", "infinity", 430 "--changelist", "i", 431 "--changelist", "o", 432 wc_dir) 433 expected_removals = { 434 sbox.ospath('A/D/G/pi') : None, 435 sbox.ospath('A/D/G/rho') : None, 436 sbox.ospath('A/D/H/chi') : None, 437 sbox.ospath('A/D/H/psi') : None, 438 } 439 verify_changelist_output(output, None, expected_removals) 440 441#---------------------------------------------------------------------- 442 443def commit_one_changelist(sbox): 444 "commit with single --changelist" 445 446 sbox.build() 447 wc_dir = sbox.wc_dir 448 449 # Add a line of text to all the versioned files in the tree. 450 mod_all_files(wc_dir, "New text.\n") 451 452 # Add files to changelists based on the last character in their names. 453 changelist_all_files(wc_dir, clname_from_lastchar_cb) 454 455 # Now, test a commit that uses a single changelist filter (--changelist a). 456 expected_output = svntest.wc.State(wc_dir, { 457 'A/B/lambda' : Item(verb='Sending'), 458 'A/B/E/alpha' : Item(verb='Sending'), 459 'A/B/E/beta' : Item(verb='Sending'), 460 'A/D/gamma' : Item(verb='Sending'), 461 'A/D/H/omega' : Item(verb='Sending'), 462 'iota' : Item(verb='Sending'), 463 }) 464 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 465 expected_status.tweak('A/mu', 'A/D/G/tau', 'A/D/G/pi', 'A/D/H/chi', 466 'A/D/H/psi', 'A/D/G/rho', wc_rev=1, status='M ') 467 expected_status.tweak('iota', 'A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta', 468 'A/D/gamma', 'A/D/H/omega', wc_rev=2, status=' ') 469 svntest.actions.run_and_verify_commit(wc_dir, 470 expected_output, 471 expected_status, 472 [], 473 wc_dir, 474 "--changelist", 475 "a") 476 477#---------------------------------------------------------------------- 478 479def commit_multiple_changelists(sbox): 480 "commit with multiple --changelist's" 481 482 sbox.build() 483 wc_dir = sbox.wc_dir 484 485 # Add a line of text to all the versioned files in the tree. 486 mod_all_files(wc_dir, "New text.\n") 487 488 # Add files to changelists based on the last character in their names. 489 changelist_all_files(wc_dir, clname_from_lastchar_cb) 490 491 # Now, test a commit that uses multiple changelist filters 492 # (--changelist=a --changelist=i). 493 expected_output = svntest.wc.State(wc_dir, { 494 'A/B/lambda' : Item(verb='Sending'), 495 'A/B/E/alpha' : Item(verb='Sending'), 496 'A/B/E/beta' : Item(verb='Sending'), 497 'A/D/gamma' : Item(verb='Sending'), 498 'A/D/H/omega' : Item(verb='Sending'), 499 'iota' : Item(verb='Sending'), 500 'A/D/G/pi' : Item(verb='Sending'), 501 'A/D/H/chi' : Item(verb='Sending'), 502 'A/D/H/psi' : Item(verb='Sending'), 503 }) 504 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 505 expected_status.tweak('A/mu', 'A/D/G/tau', 'A/D/G/rho', 506 wc_rev=1, status='M ') 507 expected_status.tweak('iota', 'A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta', 508 'A/D/gamma', 'A/D/H/omega', 'A/D/G/pi', 'A/D/H/chi', 509 'A/D/H/psi', wc_rev=2, status=' ') 510 svntest.actions.run_and_verify_commit(wc_dir, 511 expected_output, 512 expected_status, 513 [], 514 wc_dir, 515 "--changelist", "a", 516 "--changelist", "i") 517 518#---------------------------------------------------------------------- 519 520def info_with_changelists(sbox): 521 "info --changelist" 522 523 sbox.build() 524 wc_dir = sbox.wc_dir 525 526 # Add files to changelists based on the last character in their names. 527 changelist_all_files(wc_dir, clname_from_lastchar_cb) 528 529 # Now, test various combinations of changelist specification and depths. 530 for clname in [['a'], ['i'], ['a', 'i']]: 531 for depth in [None, 'files', 'infinity']: 532 533 # Figure out what we expect to see in our info output. 534 expected_paths = [] 535 if 'a' in clname: 536 if depth == 'infinity': 537 expected_paths.append('A/B/lambda') 538 expected_paths.append('A/B/E/alpha') 539 expected_paths.append('A/B/E/beta') 540 expected_paths.append('A/D/gamma') 541 expected_paths.append('A/D/H/omega') 542 if depth == 'files' or depth == 'infinity': 543 expected_paths.append('iota') 544 if 'i' in clname: 545 if depth == 'infinity': 546 expected_paths.append('A/D/G/pi') 547 expected_paths.append('A/D/H/chi') 548 expected_paths.append('A/D/H/psi') 549 expected_paths = sorted([os.path.join(wc_dir, x.replace('/', os.sep)) for x in expected_paths]) 550 551 # Build the command line. 552 args = ['info', wc_dir] 553 for cl in clname: 554 args.append('--changelist') 555 args.append(cl) 556 if depth: 557 args.append('--depth') 558 args.append(depth) 559 560 # Run 'svn info ...' 561 exit_code, output, errput = svntest.main.run_svn(None, *args) 562 563 # Filter the output for lines that begin with 'Path:', and 564 # reduce even those lines to just the actual path. 565 paths = sorted([x[6:].rstrip() for x in output if x[:6] == 'Path: ']) 566 567 # And, compare! 568 if (paths != expected_paths): 569 raise svntest.Failure("Expected paths (%s) and actual paths (%s) " 570 "don't gel" % (str(expected_paths), str(paths))) 571 572#---------------------------------------------------------------------- 573 574@XFail() 575@Issue(4826) 576def diff_with_changelists(sbox): 577 "diff --changelist (wc-wc and repos-wc)" 578 579 sbox.build() 580 wc_dir = sbox.wc_dir 581 582 # Add a line of text to all the versioned files in the tree. 583 mod_all_files(wc_dir, "New text.\n") 584 585 # Also make a property modification on each directory. 586 svntest.main.run_svn(None, 'propset', 'p', 'v', '-R', wc_dir) 587 588 # Add files to changelists based on the last character in their names. 589 changelist_all_files(wc_dir, clname_from_lastchar_cb) 590 591 # Now, test various combinations of changelist specification and depths. 592 for is_repos_wc in [0, 1]: 593 for clname in [['a'], ['a', 'i'], []]: 594 for depth in ['empty', 'files', 'immediates', 'infinity', None]: 595 for subdir in ['.', 'A', 'A/D']: 596 597 # Figure out what we expect to see in our diff output. 598 expected_paths = sorted(select_paths(sbox.ospath(subdir), depth, clname, clname_from_lastchar_cb)) 599 600 # Build the command line. 601 args = ['diff'] 602 for cl in clname: 603 args.append('--changelist') 604 args.append(cl) 605 if depth: 606 args.append('--depth') 607 args.append(depth) 608 if is_repos_wc: 609 args.append('--old') 610 args.append(sbox.repo_url + '/' + subdir) 611 args.append('--new') 612 args.append(os.path.join(wc_dir, subdir)) 613 else: 614 args.append(os.path.join(wc_dir, subdir)) 615 616 # Run 'svn diff ...' 617 exit_code, output, errput = svntest.main.run_svn(None, *args) 618 619 # Filter the output for lines that begin with 'Index:', and 620 # reduce even those lines to just the actual path. 621 paths = sorted([x[7:].rstrip() for x in output if x[:7] == 'Index: ']) 622 623 # Diff output on Win32 uses '/' path separators. 624 if sys.platform == 'win32': 625 paths = [x.replace('/', os.sep) for x in paths] 626 627 # And, compare! 628 if (paths != expected_paths): 629 raise svntest.Failure("Expected paths (%s) and actual paths (%s) " 630 "don't gel" 631 % (str(expected_paths), str(paths))) 632 633#---------------------------------------------------------------------- 634 635def propmods_with_changelists(sbox): 636 "propset/del/get/list --changelist" 637 638 sbox.build() 639 wc_dir = sbox.wc_dir 640 641 # Add files to changelists based on the last character in their names. 642 changelist_all_files(wc_dir, clname_from_lastchar_cb) 643 644 # Set property 'name'='value' on all working copy items. 645 svntest.main.run_svn(None, "pset", "--depth", "infinity", 646 "name", "value", wc_dir) 647 expected_disk = svntest.main.greek_state.copy() 648 expected_disk.add({'' : Item(props={ 'name' : 'value' })}) 649 expected_disk.tweak('A', 'A/B', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 650 'A/B/F', 'A/B/lambda', 'A/C', 'A/D', 'A/D/G', 651 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', 'A/D/H', 652 'A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi', 'A/D/gamma', 653 'A/mu', 'iota', props={ 'name' : 'value' }) 654 655 svntest.actions.verify_disk(wc_dir, expected_disk, True) 656 657 # Proplist the 'i' changelist 658 exit_code, output, errput = svntest.main.run_svn(None, "proplist", "--depth", 659 "infinity", "--changelist", 660 "i", wc_dir) 661 ### Really simple sanity check on the output of 'proplist'. If we've got 662 ### a proper proplist content checker anywhere, we should probably use it 663 ### instead. 664 if len(output) != 6: 665 raise svntest.Failure 666 667 # Remove the 'name' property from files in the 'o' and 'i' changelists. 668 svntest.main.run_svn(None, "pdel", "--depth", "infinity", 669 "name", "--changelist", "o", "--changelist", "i", 670 wc_dir) 671 expected_disk.tweak('A/D/G/pi', 'A/D/G/rho', 'A/D/H/chi', 'A/D/H/psi', 672 props={}) 673 svntest.actions.verify_disk(wc_dir, expected_disk, True) 674 675 # Add 'foo'='bar' property on all files under A/B to depth files and 676 # in changelist 'a'. 677 svntest.main.run_svn(None, "pset", "--depth", "files", 678 "foo", "bar", "--changelist", "a", 679 os.path.join(wc_dir, 'A', 'B')) 680 expected_disk.tweak('A/B/lambda', props={ 'name' : 'value', 681 'foo' : 'bar' }) 682 svntest.actions.verify_disk(wc_dir, expected_disk, True) 683 684 # Add 'bloo'='blarg' property to all files in changelist 'a'. 685 svntest.main.run_svn(None, "pset", "--depth", "infinity", 686 "bloo", "blarg", "--changelist", "a", 687 wc_dir) 688 expected_disk.tweak('A/B/lambda', props={ 'name' : 'value', 689 'foo' : 'bar', 690 'bloo' : 'blarg' }) 691 expected_disk.tweak('A/B/E/alpha', 'A/B/E/beta', 'A/D/H/omega', 'A/D/gamma', 692 'iota', props={ 'name' : 'value', 693 'bloo' : 'blarg' }) 694 svntest.actions.verify_disk(wc_dir, expected_disk, True) 695 696 # Propget 'name' in files in changelists 'a' and 'i' to depth files. 697 exit_code, output, errput = svntest.main.run_svn(None, "pget", 698 "--depth", "files", "name", 699 "--changelist", "a", 700 "--changelist", "i", 701 wc_dir) 702 verify_pget_output(output, { 703 os.path.join(wc_dir, 'iota') : 'value', 704 }) 705 706 # Propget 'name' in files in changelists 'a' and 'i' to depth infinity. 707 exit_code, output, errput = svntest.main.run_svn(None, "pget", 708 "--depth", "infinity", 709 "name", 710 "--changelist", "a", 711 "--changelist", "i", 712 wc_dir) 713 verify_pget_output(output, { 714 os.path.join(wc_dir, 'A', 'D', 'gamma') : 'value', 715 os.path.join(wc_dir, 'A', 'B', 'E', 'alpha') : 'value', 716 os.path.join(wc_dir, 'iota') : 'value', 717 os.path.join(wc_dir, 'A', 'B', 'E', 'beta') : 'value', 718 os.path.join(wc_dir, 'A', 'B', 'lambda') : 'value', 719 os.path.join(wc_dir, 'A', 'D', 'H', 'omega') : 'value', 720 }) 721 722 723#---------------------------------------------------------------------- 724 725def revert_with_changelists(sbox): 726 "revert --changelist" 727 728 sbox.build() 729 wc_dir = sbox.wc_dir 730 731 # Add files to changelists based on the last character in their names. 732 changelist_all_files(wc_dir, clname_from_lastchar_cb) 733 734 # Add a line of text to all the versioned files in the tree. 735 mod_all_files(wc_dir, "Please, oh please, revert me!\n") 736 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 737 expected_status.tweak('A/B/lambda', 'A/B/E/alpha', 'A/B/E/beta', 738 'A/D/gamma', 'A/D/H/omega', 'iota', 'A/mu', 739 'A/D/G/tau', 'A/D/G/pi', 'A/D/H/chi', 740 'A/D/H/psi', 'A/D/G/rho', status='M ') 741 svntest.actions.run_and_verify_status(wc_dir, expected_status) 742 743 # 'svn revert --changelist a WC_DIR' (without depth, no change expected) 744 svntest.main.run_svn(None, "revert", "--changelist", "a", wc_dir) 745 svntest.actions.run_and_verify_status(wc_dir, expected_status) 746 747 # 'svn revert --changelist o --depth files WC_DIR WC_DIR/A/B' (no change) 748 svntest.main.run_svn(None, "revert", "--depth", "files", 749 "--changelist", "o", 750 wc_dir, os.path.join(wc_dir, 'A', 'B')) 751 svntest.actions.run_and_verify_status(wc_dir, expected_status) 752 753 # 'svn revert --changelist a --depth files WC_DIR WC_DIR/A/B' 754 # (iota, lambda reverted) 755 svntest.main.run_svn(None, "revert", "--depth", "files", 756 "--changelist", "a", 757 wc_dir, os.path.join(wc_dir, 'A', 'B')) 758 expected_status.tweak('iota', 'A/B/lambda', status=' ') 759 svntest.actions.run_and_verify_status(wc_dir, expected_status) 760 761 # 'svn revert --changelist a --changelist i --depth infinity WC_DIR' 762 # (alpha, beta, gamma, omega, pi, chi, psi reverted) 763 svntest.main.run_svn(None, "revert", "--depth", "infinity", 764 "--changelist", "a", "--changelist", "i", 765 wc_dir) 766 expected_status.tweak('A/B/E/alpha', 'A/B/E/beta', 'A/D/gamma', 767 'A/D/H/omega', 'A/D/G/pi', 'A/D/H/chi', 768 'A/D/H/psi', status=' ') 769 svntest.actions.run_and_verify_status(wc_dir, expected_status) 770 771 # 'svn revert --depth infinity WC_DIR' (back to pristine-ness) 772 svntest.main.run_svn(None, "revert", "--depth", "infinity", 773 wc_dir) 774 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 775 svntest.actions.run_and_verify_status(wc_dir, expected_status) 776 777#---------------------------------------------------------------------- 778 779def update_with_changelists(sbox): 780 "update --changelist" 781 782 sbox.build() 783 wc_dir = sbox.wc_dir 784 785 # Add a line of text to all the versioned files in the tree, commit, update. 786 mod_all_files(wc_dir, "Added line.\n") 787 svntest.main.run_svn(None, "commit", "-m", "logmsg", wc_dir) 788 svntest.main.run_svn(None, "update", wc_dir) 789 790 # Add files to changelists based on the last character in their names. 791 changelist_all_files(wc_dir, clname_from_lastchar_cb) 792 793 ### Backdate only the files in the 'a' and 'i' changelists at depth 794 ### files under WC_DIR and WC_DIR/A/B. 795 796 # We expect update to only touch lambda and iota. 797 expected_output = svntest.wc.State(wc_dir, { 798 'A/B/lambda' : Item(status='U '), 799 'iota' : Item(status='U '), 800 }) 801 802 # Disk state should have all the files except iota and lambda 803 # carrying new text. 804 expected_disk = svntest.main.greek_state.copy() 805 expected_disk.tweak('A/B/E/alpha', 806 contents="This is the file 'alpha'.\nAdded line.\n") 807 expected_disk.tweak('A/B/E/beta', 808 contents="This is the file 'beta'.\nAdded line.\n") 809 expected_disk.tweak('A/D/gamma', 810 contents="This is the file 'gamma'.\nAdded line.\n") 811 expected_disk.tweak('A/D/H/omega', 812 contents="This is the file 'omega'.\nAdded line.\n") 813 expected_disk.tweak('A/mu', 814 contents="This is the file 'mu'.\nAdded line.\n") 815 expected_disk.tweak('A/D/G/tau', 816 contents="This is the file 'tau'.\nAdded line.\n") 817 expected_disk.tweak('A/D/G/pi', 818 contents="This is the file 'pi'.\nAdded line.\n") 819 expected_disk.tweak('A/D/H/chi', 820 contents="This is the file 'chi'.\nAdded line.\n") 821 expected_disk.tweak('A/D/H/psi', 822 contents="This is the file 'psi'.\nAdded line.\n") 823 expected_disk.tweak('A/D/G/rho', 824 contents="This is the file 'rho'.\nAdded line.\n") 825 826 # Status is clean, but with iota and lambda at r1 and all else at r2. 827 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 828 expected_status.tweak('iota', 'A/B/lambda', wc_rev=1) 829 830 # Update. 831 svntest.actions.run_and_verify_update(wc_dir, 832 expected_output, 833 expected_disk, 834 expected_status, 835 [], True, 836 "-r", "1", 837 "--changelist", "a", 838 "--changelist", "i", 839 "--depth", "files", 840 wc_dir, 841 os.path.join(wc_dir, 'A', 'B')) 842 843 ### Backdate to depth infinity all changelists "a", "i", and "o" now. 844 845 # We expect update to only touch all the files ending in 'a', 'i', 846 # and 'o' (except lambda and iota which were previously updated). 847 expected_output = svntest.wc.State(wc_dir, { 848 'A/D/G/pi' : Item(status='U '), 849 'A/D/H/chi' : Item(status='U '), 850 'A/D/H/psi' : Item(status='U '), 851 'A/D/G/rho' : Item(status='U '), 852 'A/B/E/alpha' : Item(status='U '), 853 'A/B/E/beta' : Item(status='U '), 854 'A/D/gamma' : Item(status='U '), 855 'A/D/H/omega' : Item(status='U '), 856 }) 857 858 # Disk state should have only tau and mu carrying new text. 859 expected_disk = svntest.main.greek_state.copy() 860 expected_disk.tweak('A/mu', 861 contents="This is the file 'mu'.\nAdded line.\n") 862 expected_disk.tweak('A/D/G/tau', 863 contents="This is the file 'tau'.\nAdded line.\n") 864 865 # Status is clean, but with iota and lambda at r1 and all else at r2. 866 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 867 expected_status.tweak('iota', 'A/B/lambda', 'A/D/G/pi', 'A/D/H/chi', 868 'A/D/H/psi', 'A/D/G/rho', 'A/B/E/alpha', 869 'A/B/E/beta', 'A/D/gamma', 'A/D/H/omega', wc_rev=1) 870 871 # Update. 872 svntest.actions.run_and_verify_update(wc_dir, 873 expected_output, 874 expected_disk, 875 expected_status, 876 [], True, 877 "-r", "1", 878 "--changelist", "a", 879 "--changelist", "i", 880 "--changelist", "o", 881 "--depth", "infinity", 882 wc_dir) 883 884def tree_conflicts_and_changelists_on_commit1(sbox): 885 "tree conflicts, changelists and commit" 886 svntest.actions.build_greek_tree_conflicts(sbox) 887 wc_dir = sbox.wc_dir 888 889 iota = os.path.join(wc_dir, "iota") 890 rho = os.path.join(wc_dir, "A", "D", "G", "rho") 891 892 # This file will ultimately be committed 893 svntest.main.file_append(iota, "More stuff in iota") 894 895 # Verify that the commit is blocked when we include a tree-conflicted 896 # item. 897 svntest.main.run_svn(None, "changelist", "list", iota, rho) 898 899 expected_error = ("svn: E155015: Aborting commit: '.*" + re.escape(rho) 900 + "' remains in .*conflict") 901 902 svntest.actions.run_and_verify_commit(wc_dir, 903 None, None, 904 expected_error, 905 wc_dir, 906 "--changelist", 907 "list") 908 909 # Now, test if we can commit iota without those tree-conflicts 910 # getting in the way. 911 svntest.main.run_svn(None, "changelist", "--remove", rho) 912 913 expected_output = svntest.wc.State(wc_dir, { 914 'iota' : Item(verb='Sending'), 915 }) 916 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 917 expected_status.tweak('A/D/G/pi', status='D ', treeconflict='C') 918 expected_status.tweak('A/D/G/tau', status='! ', treeconflict='C', 919 wc_rev=None) 920 expected_status.tweak('A/D/G/rho', status='A ', copied='+', 921 treeconflict='C', wc_rev='-') 922 expected_status.tweak('iota', wc_rev=3, status=' ') 923 svntest.actions.run_and_verify_commit(wc_dir, 924 expected_output, 925 expected_status, 926 [], 927 wc_dir, 928 "--changelist", 929 "list") 930 931 932def tree_conflicts_and_changelists_on_commit2(sbox): 933 "more tree conflicts, changelists and commit" 934 935 sbox.build() 936 wc_dir = sbox.wc_dir 937 938 iota = os.path.join(wc_dir, "iota") 939 A = os.path.join(wc_dir, "A",) 940 C = os.path.join(A, "C") 941 942 # Make a tree-conflict on A/C: 943 # Remove it, warp back, add a prop, update. 944 svntest.main.run_svn(None, 'delete', C) 945 946 expected_output = svntest.verify.RegexOutput( 947 "Deleting.*" + re.escape(C), 948 False) 949 svntest.actions.run_and_verify_svn(expected_output, [], 950 'commit', '-m', 'delete A/C', C) 951 952 expected_output = svntest.verify.RegexOutput( 953 "A.*" + re.escape(C), False) 954 svntest.actions.run_and_verify_svn(expected_output, [], 955 'update', C, "-r1") 956 957 expected_output = svntest.verify.RegexOutput( 958 ".*'propname' set on '" 959 + re.escape(C) + "'", False) 960 svntest.actions.run_and_verify_svn(expected_output, [], 961 'propset', 'propname', 'propval', C) 962 963 expected_output = svntest.verify.RegexOutput( 964 " C " + re.escape(C), False) 965 svntest.actions.run_and_verify_svn(expected_output, [], 966 'update', wc_dir) 967 968 969 expected_status = svntest.actions.get_virginal_state(wc_dir, 2) 970 expected_status.tweak('A/C', status='A ', copied='+', 971 treeconflict='C', wc_rev='-') 972 973 svntest.actions.run_and_verify_status(wc_dir, expected_status) 974 975 # So far so good. We have a tree-conflict on an absent dir A/C. 976 977 # Verify that the current situation does not commit. 978 expected_error = "svn: E155015: Aborting commit:.* remains in .*conflict"; 979 980 svntest.actions.run_and_verify_commit(wc_dir, 981 None, None, 982 expected_error, 983 wc_dir) 984 985 # Now try to commit with a changelist, not letting the 986 # tree-conflict get in the way. 987 svntest.main.file_append(iota, "More stuff in iota") 988 svntest.main.run_svn(None, "changelist", "list", iota) 989 990 expected_output = svntest.wc.State(wc_dir, { 991 'iota' : Item(verb='Sending'), 992 }) 993 994 expected_status.tweak('iota', wc_rev=3, status=' ') 995 996 svntest.actions.run_and_verify_commit(wc_dir, 997 expected_output, 998 expected_status, 999 [], 1000 wc_dir, 1001 "--changelist", 1002 "list") 1003 1004 1005#---------------------------------------------------------------------- 1006 1007def move_keeps_changelist(sbox): 1008 "'svn mv' of existing keeps the changelist" 1009 1010 sbox.build(read_only = True) 1011 wc_dir = sbox.wc_dir 1012 iota_path = os.path.join(wc_dir, 'iota') 1013 iota2_path = iota_path + '2' 1014 1015 # 'svn mv' of existing file should *copy* the changelist to the new place 1016 svntest.main.run_svn(None, "changelist", 'foo', iota_path) 1017 svntest.main.run_svn(None, "rename", iota_path, iota2_path) 1018 expected_infos = [ 1019 { 1020 'Name' : 'iota', 1021 'Schedule' : 'delete', 1022 'Changelist' : 'foo', 1023 }, 1024 { 1025 'Name' : 'iota2', 1026 'Schedule' : 'add', 1027 'Changelist' : 'foo', # this line fails the test 1028 }, 1029 ] 1030 svntest.actions.run_and_verify_info(expected_infos, iota_path, iota2_path) 1031 1032def move_added_keeps_changelist(sbox): 1033 "'svn mv' of added keeps the changelist" 1034 sbox.build(read_only = True) 1035 wc_dir = sbox.wc_dir 1036 repo_url = sbox.repo_url 1037 1038 kappa_path = os.path.join(wc_dir, 'kappa') 1039 kappa2_path = kappa_path + '2' 1040 1041 # add 'kappa' (do not commit!) 1042 svntest.main.file_write(kappa_path, "This is the file 'kappa'.\n") 1043 svntest.main.run_svn(None, 'add', kappa_path) 1044 1045 # 'svn mv' of added file should *move* the changelist to the new place 1046 svntest.main.run_svn(None, "changelist", 'foo', kappa_path) 1047 svntest.main.run_svn(None, "rename", kappa_path, kappa2_path) 1048 1049 # kappa not under version control 1050 svntest.actions.run_and_verify_svnversion(kappa_path, repo_url, 1051 [], ".*doesn't exist.*") 1052 # kappa2 in a changelist 1053 expected_infos = [ 1054 { 1055 'Name' : 'kappa2', 1056 'Schedule' : 'add', 1057 'Changelist' : 'foo', # this line fails the test 1058 }, 1059 ] 1060 svntest.actions.run_and_verify_info(expected_infos, kappa2_path) 1061 1062@Issue(3820) 1063def change_to_dir(sbox): 1064 "change file in changelist to dir" 1065 1066 sbox.build() 1067 1068 # No changelist initially 1069 expected_infos = [{'Name' : 'mu', 'Changelist' : None}] 1070 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1071 1072 # A/mu visible in changelist 1073 svntest.actions.run_and_verify_svn(None, [], 1074 'changelist', 'qq', sbox.ospath('A/mu')) 1075 expected_infos = [{'Name' : 'mu', 'Changelist' : 'qq'}] 1076 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1077 1078 # A/mu still visible after delete 1079 svntest.actions.run_and_verify_svn(None, [], 'rm', sbox.ospath('A/mu')) 1080 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1081 1082 # A/mu removed from changelist after replace with directory 1083 svntest.actions.run_and_verify_svn('^A|' + _re_cl_rem_pattern, [], 1084 'mkdir', sbox.ospath('A/mu')) 1085 expected_infos = [{'Changelist' : None}] # No Name for directories? 1086 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1087 1088 svntest.main.run_svn(None, "commit", "-m", "r2: replace A/mu: file->dir", 1089 sbox.ospath('A')) 1090 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1091 1092 svntest.main.run_svn(None, "update", "-r", "1", sbox.ospath('A')) 1093 expected_infos = [{'Name' : 'mu', 'Changelist' : None}] 1094 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1095 1096 # A/mu visible in changelist 1097 svntest.actions.run_and_verify_svn(None, [], 1098 'changelist', 'qq', sbox.ospath('A/mu')) 1099 expected_infos = [{'Name' : 'mu', 'Changelist' : 'qq'}] 1100 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1101 1102 # A/mu removed from changelist after replace with dir via merge 1103 svntest.main.run_svn(None, "merge", "-c", "2", sbox.ospath('A'), 1104 sbox.ospath('A')) 1105 expected_infos = [{'Changelist' : None}] # No Name for directories? 1106 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1107 1108 1109@Issue(3822) 1110def revert_deleted_in_changelist(sbox): 1111 "revert a deleted file in a changelist" 1112 1113 sbox.build(read_only = True) 1114 1115 # No changelist initially 1116 expected_infos = [{'Name' : 'mu', 'Changelist' : None}] 1117 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1118 1119 # A/mu visible in changelist 1120 svntest.actions.run_and_verify_svn(None, [], 1121 'changelist', 'qq', sbox.ospath('A/mu')) 1122 expected_infos = [{'Name' : 'mu', 'Changelist' : 'qq'}] 1123 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1124 1125 # A/mu still visible after delete 1126 svntest.actions.run_and_verify_svn(None, [], 'rm', sbox.ospath('A/mu')) 1127 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1128 1129 # A/mu still visible after revert 1130 svntest.actions.run_and_verify_svn(None, [], 1131 'revert', sbox.ospath('A/mu')) 1132 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1133 1134 # A/mu still visible after parent delete 1135 svntest.actions.run_and_verify_svn(None, [], 'rm', sbox.ospath('A')) 1136 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1137 1138 # A/mu still visible after revert 1139 svntest.actions.run_and_verify_svn(None, [], 1140 'revert', '-R', sbox.ospath('A')) 1141 svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('A/mu')) 1142 1143def add_remove_non_existent_target(sbox): 1144 "add and remove non-existent target to changelist" 1145 1146 sbox.build(read_only = True) 1147 wc_dir = sbox.wc_dir 1148 bogus_path = os.path.join(wc_dir, 'A', 'bogus') 1149 1150 expected_err = "svn: warning: W155010: The node '" + \ 1151 re.escape(os.path.abspath(bogus_path)) + \ 1152 "' was not found" 1153 1154 svntest.actions.run_and_verify_svn(None, expected_err, 1155 'changelist', 'testlist', 1156 bogus_path) 1157 1158 svntest.actions.run_and_verify_svn(None, expected_err, 1159 'changelist', bogus_path, 1160 '--remove') 1161 1162def add_remove_unversioned_target(sbox): 1163 "add and remove unversioned target to changelist" 1164 1165 sbox.build(read_only = True) 1166 unversioned = sbox.ospath('unversioned') 1167 svntest.main.file_write(unversioned, "dummy contents", 'w+') 1168 1169 expected_err = "svn: warning: W155010: The node '" + \ 1170 re.escape(os.path.abspath(unversioned)) + \ 1171 "' was not found" 1172 1173 svntest.actions.run_and_verify_svn(None, expected_err, 1174 'changelist', 'testlist', 1175 unversioned) 1176 1177 svntest.actions.run_and_verify_svn(None, expected_err, 1178 'changelist', unversioned, 1179 '--remove') 1180 1181@Issue(3985) 1182def readd_after_revert(sbox): 1183 "add new file to changelist, revert and readd" 1184 sbox.build(read_only = True) 1185 1186 dummy = sbox.ospath('dummy') 1187 svntest.main.file_write(dummy, "dummy contents") 1188 1189 sbox.simple_add('dummy') 1190 svntest.actions.run_and_verify_svn(None, [], 1191 'changelist', 'testlist', 1192 dummy) 1193 1194 sbox.simple_revert('dummy') 1195 1196 svntest.main.file_write(dummy, "dummy contents") 1197 1198 svntest.actions.run_and_verify_svn(None, [], 1199 'add', dummy) 1200 1201#---------------------------------------------------------------------- 1202 1203# A wc-wc diff returned no results if changelists were specified and the 1204# diff target dir was not the WC root. 1205@Issue(4822) 1206def diff_with_changelists_subdir(sbox): 1207 "diff --changelist (wc-wc) in subdir of WC" 1208 1209 sbox.build() 1210 wc_dir = sbox.wc_dir 1211 1212 expected_paths = sbox.ospaths(['A/D/gamma']) 1213 subdir = 'A/D' 1214 clname = 'a' 1215 1216 for path in expected_paths: 1217 svntest.main.file_append(path, "New text.\n") 1218 svntest.main.run_svn(None, "changelist", clname, *expected_paths) 1219 1220 # Run 'svn diff ...' 1221 exit_code, output, errput = svntest.main.run_svn(None, 1222 'diff', '--changelist', clname, 1223 sbox.ospath(subdir)) 1224 1225 # Filter the output for lines that begin with 'Index:', and 1226 # reduce even those lines to just the actual path. 1227 paths = sorted([x[7:].rstrip() for x in output if x[:7] == 'Index: ']) 1228 1229 # Diff output on Win32 uses '/' path separators. 1230 if sys.platform == 'win32': 1231 paths = [x.replace('/', os.sep) for x in paths] 1232 1233 # And, compare! 1234 if (paths != expected_paths): 1235 raise svntest.Failure("Expected paths (%s) and actual paths (%s) " 1236 "don't gel" 1237 % (str(expected_paths), str(paths))) 1238 1239 1240######################################################################## 1241# Run the tests 1242 1243# list all tests here, starting with None: 1244test_list = [ None, 1245 add_remove_changelists, 1246 commit_one_changelist, 1247 commit_multiple_changelists, 1248 info_with_changelists, 1249 diff_with_changelists, 1250 propmods_with_changelists, 1251 revert_with_changelists, 1252 update_with_changelists, 1253 tree_conflicts_and_changelists_on_commit1, 1254 tree_conflicts_and_changelists_on_commit2, 1255 move_keeps_changelist, 1256 move_added_keeps_changelist, 1257 change_to_dir, 1258 revert_deleted_in_changelist, 1259 add_remove_non_existent_target, 1260 add_remove_unversioned_target, 1261 readd_after_revert, 1262 diff_with_changelists_subdir, 1263 ] 1264 1265if __name__ == '__main__': 1266 svntest.main.run_tests(test_list) 1267 # NOTREACHED 1268 1269 1270### End of file. 1271