Add a little more to the svn_rangelist_intersect test to test the
[svn.git] / subversion / tests / cmdline / diff_tests.py
blob510cf0acbdd896a2919c3b698c15f7fe4dfd4aa0
1 #!/usr/bin/env python
3 # diff_tests.py: some basic diff tests
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-2007 CollabNet. All rights reserved.
11 # This software is licensed as described in the file COPYING, which
12 # you should have received as part of this distribution. The terms
13 # are also available at http://subversion.tigris.org/license-1.html.
14 # If newer versions of this license are posted there, you may use a
15 # newer version instead, at your option.
17 ######################################################################
19 # General modules
20 import sys, re, os, time
22 # Our testing module
23 import svntest
25 # (abbreviation)
26 Skip = svntest.testcase.Skip
27 XFail = svntest.testcase.XFail
28 Item = svntest.wc.StateItem
31 ######################################################################
32 # Diff output checker
34 # Looks for the correct filenames and a suitable number of +/- lines
35 # depending on whether this is an addition, modification or deletion.
37 def check_diff_output(diff_output, name, diff_type):
38 "check diff output"
40 # On Windows, diffs still display / rather than \ in paths
41 if svntest.main.windows == 1:
42 name = name.replace('\\', '/')
43 i_re = re.compile('^Index:')
44 d_re = re.compile('^Index: (\\./)?' + name)
45 p_re = re.compile('^--- (\\./)?' + name)
46 add_re = re.compile('^\\+')
47 sub_re = re.compile('^-')
49 i = 0
50 while i < len(diff_output) - 4:
52 # identify a possible diff
53 if (d_re.match(diff_output[i])
54 and p_re.match(diff_output[i+2])):
56 # count lines added and deleted
57 i += 4
58 add_lines = 0
59 sub_lines = 0
60 while i < len(diff_output) and not i_re.match(diff_output[i]):
61 if add_re.match(diff_output[i][0]):
62 add_lines += 1
63 if sub_re.match(diff_output[i][0]):
64 sub_lines += 1
65 i += 1
67 #print "add:", add_lines
68 #print "sub:", sub_lines
69 # check if this looks like the right sort of diff
70 if add_lines > 0 and sub_lines == 0 and diff_type == 'A':
71 return 0
72 if sub_lines > 0 and add_lines == 0 and diff_type == 'D':
73 return 0
74 if add_lines > 0 and sub_lines > 0 and diff_type == 'M':
75 return 0
77 else:
78 i += 1
80 # no suitable diff found
81 return 1
83 def count_diff_output(diff_output):
84 "count the number of file diffs in the output"
86 i_re = re.compile('Index:')
87 diff_count = 0
88 i = 0
89 while i < len(diff_output) - 4:
90 if i_re.match(diff_output[i]):
91 i += 4
92 diff_count += 1
93 else:
94 i += 1
96 return diff_count
98 def verify_expected_output(diff_output, expected):
99 "verify given line exists in diff output"
100 for line in diff_output:
101 if line.find(expected) != -1:
102 break
103 else:
104 raise svntest.Failure
106 def verify_excluded_output(diff_output, excluded):
107 "verify given line does not exist in diff output as diff line"
108 for line in diff_output:
109 if re.match("^(\\+|-)%s" % re.escape(excluded), line):
110 print 'Sought: %s' % excluded
111 print 'Found: %s' % line
112 raise svntest.Failure
114 def extract_diff_path(line):
115 l2 = line[(line.find("(")+1):]
116 l3 = l2[0:(l2.find(")"))]
117 return l3
119 ######################################################################
120 # diff on a repository subset and check the output
122 def diff_check_repo_subset(wc_dir, repo_subset, check_fn, do_diff_r):
123 "diff and check for part of the repository"
125 was_cwd = os.getcwd()
126 os.chdir(wc_dir)
128 diff_output, err_output = svntest.main.run_svn(None, 'diff',
129 repo_subset)
130 if check_fn(diff_output):
131 return 1
133 if do_diff_r:
134 diff_output, err_output = svntest.main.run_svn(None,
135 'diff', '-r', 'HEAD',
136 repo_subset)
137 if check_fn(diff_output):
138 return 1
140 os.chdir(was_cwd)
142 return 0
144 ######################################################################
145 # Changes makers and change checkers
147 def update_a_file():
148 "update a file"
149 svntest.main.file_write(os.path.join('A', 'B', 'E', 'alpha'), "new atext")
150 # svntest.main.file_append(, "new atext")
151 return 0
153 def check_update_a_file(diff_output):
154 "check diff for update a file"
155 return check_diff_output(diff_output,
156 os.path.join('A', 'B', 'E', 'alpha'),
157 'M')
159 def diff_check_update_a_file_repo_subset(wc_dir):
160 "diff and check update a file for a repository subset"
162 repo_subset = os.path.join('A', 'B')
163 if diff_check_repo_subset(wc_dir, repo_subset, check_update_a_file, 1):
164 return 1
166 repo_subset = os.path.join('A', 'B', 'E', 'alpha')
167 if diff_check_repo_subset(wc_dir, repo_subset, check_update_a_file, 1):
168 return 1
170 return 0
173 #----------------------------------------------------------------------
175 def add_a_file():
176 "add a file"
177 svntest.main.file_append(os.path.join('A', 'B', 'E', 'theta'), "theta")
178 svntest.main.run_svn(None, 'add', os.path.join('A', 'B', 'E', 'theta'))
179 return 0
181 def check_add_a_file(diff_output):
182 "check diff for add a file"
183 return check_diff_output(diff_output,
184 os.path.join('A', 'B', 'E', 'theta'),
185 'A')
187 def check_add_a_file_reverse(diff_output):
188 "check diff for add a file"
189 return check_diff_output(diff_output,
190 os.path.join('A', 'B', 'E', 'theta'),
191 'D')
193 def diff_check_add_a_file_repo_subset(wc_dir):
194 "diff and check add a file for a repository subset"
196 repo_subset = os.path.join('A', 'B')
197 if diff_check_repo_subset(wc_dir, repo_subset, check_add_a_file, 1):
198 return 1
200 repo_subset = os.path.join('A', 'B', 'E', 'theta')
201 ### TODO: diff -r HEAD doesn't work for added file
202 if diff_check_repo_subset(wc_dir, repo_subset, check_add_a_file, 0):
203 return 1
205 def update_added_file():
206 svntest.main.file_append(os.path.join('A', 'B', 'E', 'theta'), "net ttext")
207 "update added file"
208 return 0
210 def check_update_added_file(diff_output):
211 "check diff for update of added file"
212 return check_diff_output(diff_output,
213 os.path.join('A', 'B', 'E', 'theta'),
214 'M')
216 #----------------------------------------------------------------------
218 def add_a_file_in_a_subdir():
219 "add a file in a subdir"
220 os.mkdir(os.path.join('A', 'B', 'T'))
221 svntest.main.run_svn(None, 'add', os.path.join('A', 'B', 'T'))
222 svntest.main.file_append(os.path.join('A', 'B', 'T', 'phi'), "phi")
223 svntest.main.run_svn(None, 'add', os.path.join('A', 'B', 'T', 'phi'))
224 return 0
226 def check_add_a_file_in_a_subdir(diff_output):
227 "check diff for add a file in a subdir"
228 return check_diff_output(diff_output,
229 os.path.join('A', 'B', 'T', 'phi'),
230 'A')
232 def check_add_a_file_in_a_subdir_reverse(diff_output):
233 "check diff for add a file in a subdir"
234 return check_diff_output(diff_output,
235 os.path.join('A', 'B', 'T', 'phi'),
236 'D')
238 def diff_check_add_a_file_in_a_subdir_repo_subset(wc_dir):
239 "diff and check add a file in a subdir for a repository subset"
241 repo_subset = os.path.join('A', 'B', 'T')
242 ### TODO: diff -r HEAD doesn't work for added subdir
243 if diff_check_repo_subset(wc_dir, repo_subset,
244 check_add_a_file_in_a_subdir, 0):
245 return 1
247 repo_subset = os.path.join('A', 'B', 'T', 'phi')
248 ### TODO: diff -r HEAD doesn't work for added file in subdir
249 if diff_check_repo_subset(wc_dir, repo_subset,
250 check_add_a_file_in_a_subdir, 0):
251 return 1
253 #----------------------------------------------------------------------
255 def replace_a_file():
256 "replace a file"
257 svntest.main.run_svn(None, 'rm', os.path.join('A', 'D', 'G', 'rho'))
258 svntest.main.file_append(os.path.join('A', 'D', 'G', 'rho'), "new rho")
259 svntest.main.run_svn(None, 'add', os.path.join('A', 'D', 'G', 'rho'))
260 return 0
262 def check_replace_a_file(diff_output):
263 "check diff for replace a file"
264 return check_diff_output(diff_output,
265 os.path.join('A', 'D', 'G', 'rho'),
266 'M')
268 #----------------------------------------------------------------------
270 def update_three_files():
271 "update three files"
272 svntest.main.file_write(os.path.join('A', 'D', 'gamma'), "new gamma")
273 svntest.main.file_write(os.path.join('A', 'D', 'G', 'tau'), "new tau")
274 svntest.main.file_write(os.path.join('A', 'D', 'H', 'psi'), "new psi")
275 return 0
277 def check_update_three_files(diff_output):
278 "check update three files"
279 if check_diff_output(diff_output,
280 os.path.join('A', 'D', 'gamma'),
281 'M'):
282 return 1
283 if check_diff_output(diff_output,
284 os.path.join('A', 'D', 'G', 'tau'),
285 'M'):
286 return 1
287 if check_diff_output(diff_output,
288 os.path.join('A', 'D', 'H', 'psi'),
289 'M'):
290 return 1
291 return 0
294 ######################################################################
295 # make a change, check the diff, commit the change, check the diff
297 def change_diff_commit_diff(wc_dir, revision, change_fn, check_fn):
298 "make a change, diff, commit, update and diff again"
300 was_cwd = os.getcwd()
301 os.chdir(wc_dir)
303 svntest.main.run_svn(None,
304 'up', '-r', 'HEAD')
306 change_fn()
308 # diff without revision doesn't use an editor
309 diff_output, err_output = svntest.main.run_svn(None, 'diff')
310 if check_fn(diff_output):
311 raise svntest.Failure
313 # diff with revision runs an editor
314 diff_output, err_output = svntest.main.run_svn(None,
315 'diff', '-r', 'HEAD')
316 if check_fn(diff_output):
317 raise svntest.Failure
319 svntest.main.run_svn(None,
320 'ci', '-m', 'log msg')
321 svntest.main.run_svn(None,
322 'up')
323 diff_output, err_output = svntest.main.run_svn(None,
324 'diff', '-r', revision)
325 if check_fn(diff_output):
326 raise svntest.Failure
328 os.chdir(was_cwd)
330 ######################################################################
331 # check the diff
333 def just_diff(wc_dir, rev_check, check_fn):
334 "update and check that the given diff is seen"
336 was_cwd = os.getcwd()
337 os.chdir(wc_dir)
339 diff_output, err_output = svntest.main.run_svn(None,
340 'diff', '-r', rev_check)
341 if check_fn(diff_output):
342 raise svntest.Failure
343 os.chdir(was_cwd)
345 ######################################################################
346 # update, check the diff
348 def update_diff(wc_dir, rev_up, rev_check, check_fn):
349 "update and check that the given diff is seen"
351 was_cwd = os.getcwd()
352 os.chdir(wc_dir)
354 svntest.main.run_svn(None,
355 'up', '-r', rev_up)
357 os.chdir(was_cwd)
359 just_diff(wc_dir, rev_check, check_fn)
361 ######################################################################
362 # check a pure repository rev1:rev2 diff
364 def repo_diff(wc_dir, rev1, rev2, check_fn):
365 "check that the given pure repository diff is seen"
367 was_cwd = os.getcwd()
368 os.chdir(wc_dir)
370 diff_output, err_output = svntest.main.run_svn(None,
371 'diff', '-r',
372 `rev2` + ':' + `rev1`)
373 if check_fn(diff_output):
374 raise svntest.Failure
376 os.chdir(was_cwd)
378 ######################################################################
379 # Tests
382 # test 1
383 def diff_update_a_file(sbox):
384 "update a file"
386 sbox.build()
388 change_diff_commit_diff(sbox.wc_dir, 1,
389 update_a_file,
390 check_update_a_file)
392 # test 2
393 def diff_add_a_file(sbox):
394 "add a file"
396 sbox.build()
398 change_diff_commit_diff(sbox.wc_dir, 1,
399 add_a_file,
400 check_add_a_file)
402 #test 3
403 def diff_add_a_file_in_a_subdir(sbox):
404 "add a file in an added directory"
406 sbox.build()
408 change_diff_commit_diff(sbox.wc_dir, 1,
409 add_a_file_in_a_subdir,
410 check_add_a_file_in_a_subdir)
412 # test 4
413 def diff_replace_a_file(sbox):
414 "replace a file with a file"
416 sbox.build()
418 change_diff_commit_diff(sbox.wc_dir, 1,
419 replace_a_file,
420 check_replace_a_file)
422 # test 5
423 def diff_multiple_reverse(sbox):
424 "multiple revisions diff'd forwards and backwards"
426 sbox.build()
427 wc_dir = sbox.wc_dir
429 # rev 2
430 change_diff_commit_diff(wc_dir, 1,
431 add_a_file,
432 check_add_a_file)
434 #rev 3
435 change_diff_commit_diff(wc_dir, 2,
436 add_a_file_in_a_subdir,
437 check_add_a_file_in_a_subdir)
439 #rev 4
440 change_diff_commit_diff(wc_dir, 3,
441 update_a_file,
442 check_update_a_file)
444 # check diffs both ways
445 update_diff(wc_dir, 4, 1, check_update_a_file)
446 just_diff(wc_dir, 1, check_add_a_file_in_a_subdir)
447 just_diff(wc_dir, 1, check_add_a_file)
448 update_diff(wc_dir, 1, 4, check_update_a_file)
449 just_diff(wc_dir, 4, check_add_a_file_in_a_subdir_reverse)
450 just_diff(wc_dir, 4, check_add_a_file_reverse)
452 # check pure repository diffs
453 repo_diff(wc_dir, 4, 1, check_update_a_file)
454 repo_diff(wc_dir, 4, 1, check_add_a_file_in_a_subdir)
455 repo_diff(wc_dir, 4, 1, check_add_a_file)
456 repo_diff(wc_dir, 1, 4, check_update_a_file)
457 # ### TODO: directory delete doesn't work yet
458 # repo_diff(wc_dir, 1, 4, check_add_a_file_in_a_subdir_reverse)
459 repo_diff(wc_dir, 1, 4, check_add_a_file_reverse)
461 # test 6
462 def diff_non_recursive(sbox):
463 "non-recursive behaviour"
465 sbox.build()
466 wc_dir = sbox.wc_dir
468 change_diff_commit_diff(wc_dir, 1,
469 update_three_files,
470 check_update_three_files)
472 # The changes are in: ./A/D/gamma
473 # ./A/D/G/tau
474 # ./A/D/H/psi
475 # When checking D recursively there are three changes. When checking
476 # D non-recursively there is only one change. When checking G
477 # recursively, there is only one change even though D is the anchor
479 # full diff has three changes
480 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-r', '1',
481 os.path.join(wc_dir, 'A', 'D'))
482 if count_diff_output(diff_output) != 3:
483 raise svntest.Failure
485 # non-recursive has one change
486 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-r', '1', '-N',
487 os.path.join(wc_dir, 'A', 'D'))
488 if count_diff_output(diff_output) != 1:
489 raise svntest.Failure
491 # diffing a directory doesn't pick up other diffs in the anchor
492 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-r', '1',
493 os.path.join(wc_dir,
494 'A', 'D', 'G'))
495 if count_diff_output(diff_output) != 1:
496 raise svntest.Failure
499 # test 7
500 def diff_repo_subset(sbox):
501 "diff only part of the repository"
503 sbox.build()
504 wc_dir = sbox.wc_dir
506 was_cwd = os.getcwd()
507 os.chdir(wc_dir)
509 update_a_file()
510 add_a_file()
511 add_a_file_in_a_subdir()
513 os.chdir(was_cwd)
515 if diff_check_update_a_file_repo_subset(wc_dir):
516 raise svntest.Failure
518 if diff_check_add_a_file_repo_subset(wc_dir):
519 raise svntest.Failure
521 if diff_check_add_a_file_in_a_subdir_repo_subset(wc_dir):
522 raise svntest.Failure
525 # test 8
526 def diff_non_version_controlled_file(sbox):
527 "non version controlled files"
529 sbox.build()
530 wc_dir = sbox.wc_dir
532 svntest.main.file_append(os.path.join(wc_dir, 'A', 'D', 'foo'), "a new file")
534 diff_output, err_output = svntest.main.run_svn(1, 'diff',
535 os.path.join(wc_dir,
536 'A', 'D', 'foo'))
538 if count_diff_output(diff_output) != 0: raise svntest.Failure
540 # At one point this would crash, so we would only get a 'Segmentation Fault'
541 # error message. The appropriate response is a few lines of errors. I wish
542 # there was a way to figure out if svn crashed, but all run_svn gives us is
543 # the output, so here we are...
544 for line in err_output:
545 if re.search("foo' is not under version control$", line):
546 break
547 else:
548 raise svntest.Failure
550 # test 9
551 def diff_pure_repository_update_a_file(sbox):
552 "pure repository diff update a file"
554 sbox.build()
555 wc_dir = sbox.wc_dir
557 os.chdir(wc_dir)
559 # rev 2
560 update_a_file()
561 svntest.main.run_svn(None,
562 'ci', '-m', 'log msg')
564 # rev 3
565 add_a_file_in_a_subdir()
566 svntest.main.run_svn(None,
567 'ci', '-m', 'log msg')
569 # rev 4
570 add_a_file()
571 svntest.main.run_svn(None,
572 'ci', '-m', 'log msg')
574 # rev 5
575 update_added_file()
576 svntest.main.run_svn(None,
577 'ci', '-m', 'log msg')
579 svntest.main.run_svn(None,
580 'up', '-r', '2')
582 url = sbox.repo_url
584 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-c', '2',
585 url)
586 if check_update_a_file(diff_output): raise svntest.Failure
588 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-r', '1:2')
589 if check_update_a_file(diff_output): raise svntest.Failure
591 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-c', '3',
592 url)
593 if check_add_a_file_in_a_subdir(diff_output): raise svntest.Failure
595 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-r', '2:3')
596 if check_add_a_file_in_a_subdir(diff_output): raise svntest.Failure
598 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-c', '5',
599 url)
600 if check_update_added_file(diff_output): raise svntest.Failure
602 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-r', '4:5')
603 if check_update_added_file(diff_output): raise svntest.Failure
605 diff_output, err_output = svntest.main.run_svn(None, 'diff', '-r', 'head')
606 if check_add_a_file_in_a_subdir_reverse(diff_output): raise svntest.Failure
609 # test 10
610 def diff_only_property_change(sbox):
611 "diff when property was changed but text was not"
613 sbox.build()
614 wc_dir = sbox.wc_dir
616 expected_output = [
617 "\n",
618 "Property changes on: iota\n",
619 "___________________________________________________________________\n",
620 "Added: svn:eol-style\n",
621 " + native\n",
622 "\n" ]
624 expected_reverse_output = list(expected_output)
625 expected_reverse_output[3] = expected_reverse_output[3].replace("Added",
626 "Deleted")
627 expected_reverse_output[4] = " - native\n"
630 os.chdir(sbox.wc_dir)
631 svntest.actions.run_and_verify_svn(None, None, [],
632 'propset',
633 'svn:eol-style', 'native', 'iota')
635 svntest.actions.run_and_verify_svn(None, None, [],
636 'ci', '-m', 'empty-msg')
638 svntest.actions.run_and_verify_svn(None, expected_output, [],
639 'diff', '-r', '1:2')
641 svntest.actions.run_and_verify_svn(None, expected_output, [],
642 'diff', '-c', '2')
644 svntest.actions.run_and_verify_svn(None, expected_reverse_output, [],
645 'diff', '-r', '2:1')
647 svntest.actions.run_and_verify_svn(None, expected_reverse_output, [],
648 'diff', '-c', '-2')
650 svntest.actions.run_and_verify_svn(None, expected_output, [],
651 'diff', '-r', '1')
653 svntest.actions.run_and_verify_svn(None, expected_output, [],
654 'diff', '-r', 'PREV', 'iota')
658 #----------------------------------------------------------------------
659 # Regression test for issue #1019: make sure we don't try to display
660 # diffs when the file is marked as a binary type. This tests all 3
661 # uses of 'svn diff': wc-wc, wc-repos, repos-repos.
663 def dont_diff_binary_file(sbox):
664 "don't diff file marked as binary type"
666 sbox.build()
667 wc_dir = sbox.wc_dir
669 # Add a binary file to the project.
670 theta_contents = svntest.main.file_read(
671 os.path.join(sys.path[0], "theta.bin"), 'rb')
672 # Write PNG file data into 'A/theta'.
673 theta_path = os.path.join(wc_dir, 'A', 'theta')
674 svntest.main.file_write(theta_path, theta_contents, 'wb')
676 svntest.main.run_svn(None, 'add', theta_path)
678 # Created expected output tree for 'svn ci'
679 expected_output = svntest.wc.State(wc_dir, {
680 'A/theta' : Item(verb='Adding (bin)'),
683 # Create expected status tree
684 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
685 expected_status.add({
686 'A/theta' : Item(status=' ', wc_rev=2),
689 # Commit the new binary file, creating revision 2.
690 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
691 expected_status, None, wc_dir)
693 # Update the whole working copy to HEAD (rev 2)
694 expected_output = svntest.wc.State(wc_dir, {})
696 expected_disk = svntest.main.greek_state.copy()
697 expected_disk.add({
698 'A/theta' : Item(theta_contents,
699 props={'svn:mime-type' : 'application/octet-stream'}),
702 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
703 expected_status.add({
704 'A/theta' : Item(status=' ', wc_rev=2),
707 svntest.actions.run_and_verify_update(wc_dir,
708 expected_output,
709 expected_disk,
710 expected_status,
711 None, None, None, None, None,
712 1) # verify props, too.
714 # Make a local mod to the binary file.
715 svntest.main.file_append(theta_path, "some extra junk")
717 # First diff use-case: plain old 'svn diff wc' will display any
718 # local changes in the working copy. (diffing working
719 # vs. text-base)
721 re_nodisplay = re.compile('^Cannot display:')
723 stdout, stderr = svntest.main.run_svn(None, 'diff', wc_dir)
725 for line in stdout:
726 if (re_nodisplay.match(line)):
727 break
728 else:
729 raise svntest.Failure
731 # Second diff use-case: 'svn diff -r1 wc' compares the wc against a
732 # the first revision in the repository.
734 stdout, stderr = svntest.main.run_svn(None,
735 'diff', '-r', '1', wc_dir)
737 for line in stdout:
738 if (re_nodisplay.match(line)):
739 break
740 else:
741 raise svntest.Failure
743 # Now commit the local mod, creating rev 3.
744 expected_output = svntest.wc.State(wc_dir, {
745 'A/theta' : Item(verb='Sending'),
748 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
749 expected_status.add({
750 'A/theta' : Item(status=' ', wc_rev=3),
753 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
754 expected_status, None, wc_dir)
756 # Third diff use-case: 'svn diff -r2:3 wc' will compare two
757 # repository trees.
759 stdout, stderr = svntest.main.run_svn(None,
760 'diff', '-r', '2:3', wc_dir)
762 for line in stdout:
763 if (re_nodisplay.match(line)):
764 break
765 else:
766 raise svntest.Failure
769 def diff_nonextant_urls(sbox):
770 "svn diff errors against a non-existent URL"
772 sbox.build(create_wc = False)
773 non_extant_url = sbox.repo_url + '/A/does_not_exist'
774 extant_url = sbox.repo_url + '/A/mu'
776 diff_output, err_output = svntest.main.run_svn(1,
777 'diff',
778 '--old', non_extant_url,
779 '--new', extant_url)
780 for line in err_output:
781 if re.search('was not found in the repository at revision', line):
782 break
783 else:
784 raise svntest.Failure
786 diff_output, err_output = svntest.main.run_svn(1,
787 'diff',
788 '--old', extant_url,
789 '--new', non_extant_url)
790 for line in err_output:
791 if re.search('was not found in the repository at revision', line):
792 break
793 else:
794 raise svntest.Failure
796 def diff_head_of_moved_file(sbox):
797 "diff against the head of a moved file"
799 sbox.build()
800 mu_path = os.path.join(sbox.wc_dir, 'A', 'mu')
801 new_mu_path = mu_path + '.new'
803 svntest.main.run_svn(None, 'mv', mu_path, new_mu_path)
805 # Modify the file to ensure that the diff is non-empty.
806 svntest.main.file_append(new_mu_path, "\nActually, it's a new mu.")
808 svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
809 'diff', '-r', 'HEAD', new_mu_path)
813 #----------------------------------------------------------------------
814 # Regression test for issue #977: make 'svn diff -r BASE:N' compare a
815 # repository tree against the wc's text-bases, rather than the wc's
816 # working files. This is a long test, which checks many variations.
818 def diff_base_to_repos(sbox):
819 "diff text-bases against repository"
821 sbox.build()
822 wc_dir = sbox.wc_dir
824 iota_path = os.path.join(sbox.wc_dir, 'iota')
825 newfile_path = os.path.join(sbox.wc_dir, 'A', 'D', 'newfile')
826 mu_path = os.path.join(sbox.wc_dir, 'A', 'mu')
828 # Make changes to iota, commit r2, update to HEAD (r2).
829 svntest.main.file_append(iota_path, "some rev2 iota text.\n")
831 expected_output = svntest.wc.State(wc_dir, {
832 'iota' : Item(verb='Sending'),
835 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
836 expected_status.tweak('iota', wc_rev=2)
838 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
839 expected_status, None, wc_dir)
841 expected_output = svntest.wc.State(wc_dir, {})
842 expected_disk = svntest.main.greek_state.copy()
843 expected_disk.tweak('iota',
844 contents=\
845 "This is the file 'iota'.\nsome rev2 iota text.\n")
846 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
847 svntest.actions.run_and_verify_update(wc_dir, expected_output,
848 expected_disk, expected_status)
850 # Now make another local mod to iota.
851 svntest.main.file_append(iota_path, "an iota local mod.\n")
853 # If we run 'svn diff -r 1', we should see diffs that include *both*
854 # the rev2 changes and local mods. That's because the working files
855 # are being compared to the repository.
856 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
857 'diff',
858 '-r', '1', wc_dir)
860 # Makes diff output look the same on all platforms.
861 def strip_eols(lines):
862 return [x.replace("\r", "").replace("\n", "") for x in lines]
864 expected_output_lines = [
865 "Index: svn-test-work/working_copies/diff_tests-14/iota\n",
866 "===================================================================\n",
867 "--- svn-test-work/working_copies/diff_tests-14/iota\t(revision 1)\n",
868 "+++ svn-test-work/working_copies/diff_tests-14/iota\t(working copy)\n",
869 "@@ -1 +1,3 @@\n",
870 " This is the file 'iota'.\n",
871 "+some rev2 iota text.\n",
872 "+an iota local mod.\n"]
874 if strip_eols(diff_output) != strip_eols(expected_output_lines):
875 raise svntest.Failure
877 # If we run 'svn diff -r BASE:1', we should see diffs that only show
878 # the rev2 changes and NOT the local mods. That's because the
879 # text-bases are being compared to the repository.
880 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
881 'diff', '-r', 'BASE:1',
882 wc_dir)
883 expected_output_lines = [
884 "Index: svn-test-work/working_copies/diff_tests-14/iota\n",
885 "===================================================================\n",
886 "--- svn-test-work/working_copies/diff_tests-14/iota\t(working copy)\n",
887 "+++ svn-test-work/working_copies/diff_tests-14/iota\t(revision 1)\n",
888 "@@ -1,2 +1 @@\n",
889 " This is the file 'iota'.\n",
890 "-some rev2 iota text.\n"]
892 if strip_eols(diff_output) != strip_eols(expected_output_lines):
893 raise svntest.Failure
895 # But that's not all folks... no, no, we're just getting started
896 # here! There are so many other tests to do.
898 # For example, we just ran 'svn diff -rBASE:1'. The output should
899 # look exactly the same as 'svn diff -r2:1'. (If you remove the
900 # header commentary)
901 diff_output2, err = svntest.actions.run_and_verify_svn(None, None, [],
902 'diff', '-r', '2:1',
903 wc_dir)
905 diff_output[2:4] = []
906 diff_output2[2:4] = []
908 if (diff_output2 != diff_output):
909 raise svntest.Failure
911 # and similarly, does 'svn diff -r1:2' == 'svn diff -r1:BASE' ?
912 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
913 'diff',
914 '-r', '1:2', wc_dir)
916 diff_output2, err = svntest.actions.run_and_verify_svn(None, None, [],
917 'diff',
918 '-r', '1:BASE',
919 wc_dir)
921 diff_output[2:4] = []
922 diff_output2[2:4] = []
924 if (diff_output2 != diff_output):
925 raise svntest.Failure
927 # Now we schedule an addition and a deletion.
928 svntest.main.file_append(newfile_path, "Contents of newfile\n")
929 svntest.main.run_svn(None, 'add', newfile_path)
930 svntest.main.run_svn(None, 'rm', mu_path)
932 expected_output = svntest.actions.get_virginal_state(wc_dir, 2)
933 expected_output.add({
934 'A/D/newfile' : Item(status='A ', wc_rev=0),
936 expected_output.tweak('A/mu', status='D ')
937 expected_output.tweak('iota', status='M ')
938 svntest.actions.run_and_verify_status(wc_dir, expected_output)
940 # once again, verify that -r1:2 and -r1:BASE look the same, as do
941 # -r2:1 and -rBASE:1. None of these diffs should mention the
942 # scheduled addition or deletion.
943 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
944 'diff', '-r',
945 '1:2', wc_dir)
947 diff_output2, err = svntest.actions.run_and_verify_svn(None, None, [],
948 'diff', '-r',
949 '1:BASE', wc_dir)
951 diff_output3, err = svntest.actions.run_and_verify_svn(None, None, [],
952 'diff', '-r',
953 '2:1', wc_dir)
955 diff_output4, err = svntest.actions.run_and_verify_svn(None, None, [],
956 'diff', '-r',
957 'BASE:1', wc_dir)
959 diff_output[2:4] = []
960 diff_output2[2:4] = []
961 diff_output3[2:4] = []
962 diff_output4[2:4] = []
964 if (diff_output != diff_output2):
965 raise svntest.Failure
967 if (diff_output3 != diff_output4):
968 raise svntest.Failure
970 # Great! So far, so good. Now we commit our three changes (a local
971 # mod, an addition, a deletion) and update to HEAD (r3).
972 expected_output = svntest.wc.State(wc_dir, {
973 'iota' : Item(verb='Sending'),
974 'A/mu' : Item(verb='Deleting'),
975 'A/D/newfile' : Item(verb='Adding')
977 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
978 expected_status.tweak('iota', wc_rev=3)
979 expected_status.remove('A/mu')
980 expected_status.add({
981 'A/D/newfile' : Item(status=' ', wc_rev=3),
983 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
984 expected_status, None, wc_dir)
986 expected_output = svntest.wc.State(wc_dir, {})
987 expected_disk = svntest.main.greek_state.copy()
988 expected_disk.tweak('iota',
989 contents="This is the file 'iota'.\n" + \
990 "some rev2 iota text.\nan iota local mod.\n")
991 expected_disk.add({'A/D/newfile' : Item("Contents of newfile\n")})
992 expected_disk.remove('A/mu')
994 expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
995 expected_status.remove('A/mu')
996 expected_status.add({
997 'A/D/newfile' : Item(status=' ', wc_rev=3),
999 svntest.actions.run_and_verify_update(wc_dir, expected_output,
1000 expected_disk, expected_status)
1002 # Now 'svn diff -r3:2' should == 'svn diff -rBASE:2', showing the
1003 # removal of changes to iota, the adding of mu, and deletion of newfile.
1004 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1005 'diff', '-r',
1006 '3:2', wc_dir)
1008 diff_output2, err = svntest.actions.run_and_verify_svn(None, None, [],
1009 'diff', '-r',
1010 'BASE:2', wc_dir)
1012 # to do the comparison, remove all output lines starting with +++ or ---
1013 re_infoline = re.compile('^(\+\+\+|---).*$')
1014 list1 = []
1015 list2 = []
1017 for line in diff_output:
1018 if not re_infoline.match(line):
1019 list1.append(line)
1021 for line in diff_output2:
1022 if not re_infoline.match(line):
1023 list2.append(line)
1025 if list1 != list2:
1026 raise svntest.Failure
1029 #----------------------------------------------------------------------
1030 # This is a simple regression test for issue #891, whereby ra_neon's
1031 # REPORT request would fail, because the object no longer exists in HEAD.
1033 def diff_deleted_in_head(sbox):
1034 "repos-repos diff on item deleted from HEAD"
1036 sbox.build()
1037 wc_dir = sbox.wc_dir
1039 A_path = os.path.join(sbox.wc_dir, 'A')
1040 mu_path = os.path.join(sbox.wc_dir, 'A', 'mu')
1042 # Make a change to mu, commit r2, update.
1043 svntest.main.file_append(mu_path, "some rev2 mu text.\n")
1045 expected_output = svntest.wc.State(wc_dir, {
1046 'A/mu' : Item(verb='Sending'),
1048 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1049 expected_status.tweak('A/mu', wc_rev=2)
1051 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1052 expected_status, None, wc_dir)
1054 expected_output = svntest.wc.State(wc_dir, {})
1055 expected_disk = svntest.main.greek_state.copy()
1056 expected_disk.tweak('A/mu',
1057 contents="This is the file 'mu'.\nsome rev2 mu text.\n")
1058 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1059 svntest.actions.run_and_verify_update(wc_dir, expected_output,
1060 expected_disk, expected_status)
1062 # Now delete the whole directory 'A', and commit as r3.
1063 svntest.main.run_svn(None, 'rm', A_path)
1064 expected_output = svntest.wc.State(wc_dir, {
1065 'A' : Item(verb='Deleting'),
1067 expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
1068 expected_status.remove('A', 'A/B', 'A/B/E', 'A/B/E/beta', 'A/B/E/alpha',
1069 'A/B/F', 'A/B/lambda', 'A/D', 'A/D/G', 'A/D/G/rho',
1070 'A/D/G/pi', 'A/D/G/tau', 'A/D/H', 'A/D/H/psi',
1071 'A/D/H/omega', 'A/D/H/chi', 'A/D/gamma', 'A/mu',
1072 'A/C')
1074 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1075 expected_status, None, wc_dir)
1077 # Doing an 'svn diff -r1:2' on the URL of directory A should work,
1078 # especially over the DAV layer.
1079 the_url = sbox.repo_url + '/A'
1080 diff_output = svntest.actions.run_and_verify_svn(None, None, [],
1081 'diff', '-r',
1082 '1:2', the_url + "@2")
1085 #----------------------------------------------------------------------
1086 def diff_targets(sbox):
1087 "select diff targets"
1089 sbox.build()
1090 os.chdir(sbox.wc_dir)
1092 update_a_file()
1093 add_a_file()
1095 update_path = os.path.join('A', 'B', 'E', 'alpha')
1096 add_path = os.path.join('A', 'B', 'E', 'theta')
1097 parent_path = os.path.join('A', 'B', 'E')
1098 update_url = sbox.repo_url + '/A/B/E/alpha'
1099 parent_url = sbox.repo_url + '/A/B/E'
1101 diff_output, err_output = svntest.main.run_svn(None, 'diff',
1102 update_path, add_path)
1103 if check_update_a_file(diff_output) or check_add_a_file(diff_output):
1104 raise svntest.Failure
1106 diff_output, err_output = svntest.main.run_svn(None, 'diff',
1107 update_path)
1108 if check_update_a_file(diff_output) or not check_add_a_file(diff_output):
1109 raise svntest.Failure
1111 diff_output, err_output = svntest.main.run_svn(None, 'diff',
1112 '--old', parent_path,
1113 'alpha', 'theta')
1114 if check_update_a_file(diff_output) or check_add_a_file(diff_output):
1115 raise svntest.Failure
1117 diff_output, err_output = svntest.main.run_svn(None, 'diff',
1118 '--old', parent_path,
1119 'theta')
1120 if not check_update_a_file(diff_output) or check_add_a_file(diff_output):
1121 raise svntest.Failure
1123 diff_output, err_output = svntest.main.run_svn(None,
1124 'ci', '-m', 'log msg')
1126 diff_output, err_output = svntest.main.run_svn(1,
1127 'diff', '-r1:2',
1128 update_path, add_path)
1130 regex = 'svn: Unable to find repository location for \'.*\''
1131 for line in err_output:
1132 if re.match(regex, line):
1133 break
1134 else:
1135 raise svntest.Failure
1137 diff_output, err_output = svntest.main.run_svn(1,
1138 'diff', '-r1:2',
1139 add_path)
1140 for line in err_output:
1141 if re.match(regex, line):
1142 break
1143 else:
1144 raise svntest.Failure
1146 diff_output, err_output = svntest.main.run_svn(1,
1147 'diff', '-r1:2',
1148 '--old', parent_path,
1149 'alpha', 'theta')
1150 regex = 'svn: \'.*\' was not found in the repository'
1151 for line in err_output:
1152 if re.match(regex, line):
1153 break
1154 else:
1155 raise svntest.Failure
1157 diff_output, err_output = svntest.main.run_svn(None,
1158 'diff', '-r1:2',
1159 '--old', parent_path,
1160 'alpha')
1161 if check_update_a_file(diff_output) or not check_add_a_file(diff_output):
1162 raise svntest.Failure
1165 #----------------------------------------------------------------------
1166 def diff_branches(sbox):
1167 "diff for branches"
1169 sbox.build()
1171 A_url = sbox.repo_url + '/A'
1172 A2_url = sbox.repo_url + '/A2'
1174 svntest.actions.run_and_verify_svn(None, None, [],
1175 'cp', '-m', 'log msg',
1176 A_url, A2_url)
1178 svntest.actions.run_and_verify_svn(None, None, [],
1179 'up', sbox.wc_dir)
1181 A_alpha = os.path.join(sbox.wc_dir, 'A', 'B', 'E', 'alpha')
1182 A2_alpha = os.path.join(sbox.wc_dir, 'A2', 'B', 'E', 'alpha')
1184 svntest.main.file_append(A_alpha, "\nfoo\n")
1185 svntest.actions.run_and_verify_svn(None, None, [],
1186 'ci', '-m', 'log msg', sbox.wc_dir)
1188 svntest.main.file_append(A2_alpha, "\nbar\n")
1189 svntest.actions.run_and_verify_svn(None, None, [],
1190 'ci', '-m', 'log msg', sbox.wc_dir)
1192 svntest.main.file_append(A_alpha, "zig\n")
1194 # Compare repository file on one branch against repository file on
1195 # another branch
1196 rel_path = os.path.join('B', 'E', 'alpha')
1197 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1198 'diff',
1199 '--old', A_url,
1200 '--new', A2_url,
1201 rel_path)
1202 verify_expected_output(diff_output, "-foo")
1203 verify_expected_output(diff_output, "+bar")
1205 # Same again but using whole branch
1206 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1207 'diff',
1208 '--old', A_url,
1209 '--new', A2_url)
1210 verify_expected_output(diff_output, "-foo")
1211 verify_expected_output(diff_output, "+bar")
1213 # Compare two repository files on different branches
1214 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1215 'diff',
1216 A_url + '/B/E/alpha',
1217 A2_url + '/B/E/alpha')
1218 verify_expected_output(diff_output, "-foo")
1219 verify_expected_output(diff_output, "+bar")
1221 # Compare two versions of a file on a single branch
1222 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1223 'diff',
1224 A_url + '/B/E/alpha@2',
1225 A_url + '/B/E/alpha@3')
1226 verify_expected_output(diff_output, "+foo")
1228 # Compare identical files on different branches
1229 diff_output, err = svntest.actions.run_and_verify_svn(
1230 None, [], [],
1231 'diff', A_url + '/B/E/alpha@2', A2_url + '/B/E/alpha@3')
1234 #----------------------------------------------------------------------
1235 def diff_repos_and_wc(sbox):
1236 "diff between repos URLs and WC paths"
1238 sbox.build()
1240 A_url = sbox.repo_url + '/A'
1241 A2_url = sbox.repo_url + '/A2'
1243 svntest.actions.run_and_verify_svn(None, None, [],
1244 'cp', '-m', 'log msg',
1245 A_url, A2_url)
1247 svntest.actions.run_and_verify_svn(None, None, [],
1248 'up', sbox.wc_dir)
1250 A_alpha = os.path.join(sbox.wc_dir, 'A', 'B', 'E', 'alpha')
1251 A2_alpha = os.path.join(sbox.wc_dir, 'A2', 'B', 'E', 'alpha')
1253 svntest.main.file_append(A_alpha, "\nfoo\n")
1254 svntest.actions.run_and_verify_svn(None, None, [],
1255 'ci', '-m', 'log msg', sbox.wc_dir)
1257 svntest.main.file_append(A2_alpha, "\nbar\n")
1258 svntest.actions.run_and_verify_svn(None, None, [],
1259 'ci', '-m', 'log msg', sbox.wc_dir)
1261 svntest.main.file_append(A_alpha, "zig\n")
1263 # Compare working file on one branch against repository file on
1264 # another branch
1265 A_path = os.path.join(sbox.wc_dir, 'A')
1266 rel_path = os.path.join('B', 'E', 'alpha')
1267 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1268 'diff',
1269 '--old', A2_url,
1270 '--new', A_path,
1271 rel_path)
1272 verify_expected_output(diff_output, "-bar")
1273 verify_expected_output(diff_output, "+foo")
1274 verify_expected_output(diff_output, "+zig")
1276 # Same again but using whole branch
1277 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1278 'diff',
1279 '--old', A2_url,
1280 '--new', A_path)
1281 verify_expected_output(diff_output, "-bar")
1282 verify_expected_output(diff_output, "+foo")
1283 verify_expected_output(diff_output, "+zig")
1285 #----------------------------------------------------------------------
1286 def diff_file_urls(sbox):
1287 "diff between two file URLs (issue #1311)"
1289 sbox.build()
1291 iota_path = os.path.join(sbox.wc_dir, 'iota')
1292 iota_url = sbox.repo_url + '/iota'
1293 iota_copy_path = os.path.join(sbox.wc_dir, 'A', 'iota')
1294 iota_copy_url = sbox.repo_url + '/A/iota'
1295 iota_copy2_url = sbox.repo_url + '/A/iota2'
1297 # Put some different text into iota, and commit.
1298 os.remove(iota_path)
1299 svntest.main.file_append(iota_path, "foo\nbar\nsnafu\n")
1301 svntest.actions.run_and_verify_svn(None, None, [],
1302 'ci', '-m', 'log msg', iota_path)
1304 # Now, copy the file elsewhere, twice.
1305 svntest.actions.run_and_verify_svn(None, None, [],
1306 'cp', '-m', 'log msg',
1307 iota_url, iota_copy_url)
1309 svntest.actions.run_and_verify_svn(None, None, [],
1310 'cp', '-m', 'log msg',
1311 iota_url, iota_copy2_url)
1313 # Update (to get the copies)
1314 svntest.actions.run_and_verify_svn(None, None, [],
1315 'up', sbox.wc_dir)
1317 # Now, make edits to one of the copies of iota, and commit.
1318 os.remove(iota_copy_path)
1319 svntest.main.file_append(iota_copy_path, "foo\nsnafu\nabcdefg\nopqrstuv\n")
1321 svntest.actions.run_and_verify_svn(None, None, [],
1322 'ci', '-m', 'log msg', iota_copy_path)
1324 # Finally, do a diff between the first and second copies of iota,
1325 # and verify that we got the expected lines. And then do it in reverse!
1326 out, err = svntest.actions.run_and_verify_svn(None, None, [],
1327 'diff',
1328 iota_copy_url, iota_copy2_url)
1330 verify_expected_output(out, "+bar")
1331 verify_expected_output(out, "-abcdefg")
1332 verify_expected_output(out, "-opqrstuv")
1334 out, err = svntest.actions.run_and_verify_svn(None, None, [],
1335 'diff',
1336 iota_copy2_url, iota_copy_url)
1338 verify_expected_output(out, "-bar")
1339 verify_expected_output(out, "+abcdefg")
1340 verify_expected_output(out, "+opqrstuv")
1342 #----------------------------------------------------------------------
1343 def diff_prop_change_local_edit(sbox):
1344 "diff a property change plus a local edit"
1346 sbox.build()
1348 iota_path = os.path.join(sbox.wc_dir, 'iota')
1349 iota_url = sbox.repo_url + '/iota'
1351 # Change a property on iota, and commit.
1352 svntest.actions.run_and_verify_svn(None, None, [],
1353 'propset', 'pname', 'pvalue', iota_path)
1354 svntest.actions.run_and_verify_svn(None, None, [],
1355 'ci', '-m', 'log msg', iota_path)
1357 # Make local edits to iota.
1358 svntest.main.file_append(iota_path, "\nMore text.\n")
1360 # diff r1:COMMITTED should show the property change but not the local edit.
1361 out, err = svntest.actions.run_and_verify_svn(None, None, [],
1362 'diff',
1363 '-r1:COMMITTED', iota_path)
1364 for line in out:
1365 if line.find("+More text.") != -1:
1366 raise svntest.Failure
1367 verify_expected_output(out, " + pvalue")
1369 # diff r1:BASE should show the property change but not the local edit.
1370 out, err = svntest.actions.run_and_verify_svn(None, None, [],
1371 'diff', '-r1:BASE', iota_path)
1372 for line in out:
1373 if line.find("+More text.") != -1:
1374 raise svntest.Failure # fails at r7481
1375 verify_expected_output(out, " + pvalue") # fails at r7481
1377 # diff r1:WC should show the local edit as well as the property change.
1378 out, err = svntest.actions.run_and_verify_svn(None, None, [],
1379 'diff', '-r1', iota_path)
1380 verify_expected_output(out, "+More text.") # fails at r7481
1381 verify_expected_output(out, " + pvalue")
1383 #----------------------------------------------------------------------
1384 def check_for_omitted_prefix_in_path_component(sbox):
1385 "check for omitted prefix in path component"
1387 sbox.build()
1388 svntest.actions.do_sleep_for_timestamps()
1390 prefix_path = os.path.join(sbox.wc_dir, 'prefix_mydir')
1391 svntest.actions.run_and_verify_svn(None, None, [],
1392 'mkdir', prefix_path)
1393 other_prefix_path = os.path.join(sbox.wc_dir, 'prefix_other')
1394 svntest.actions.run_and_verify_svn(None, None, [],
1395 'mkdir', other_prefix_path)
1397 svntest.actions.run_and_verify_svn(None, None, [],
1398 'ci', '-m', 'log msg', sbox.wc_dir)
1401 file_path = os.path.join(prefix_path, "test.txt")
1402 svntest.main.file_write(file_path, "Hello\nThere\nIota\n")
1404 svntest.actions.run_and_verify_svn(None, None, [],
1405 'add', file_path)
1407 svntest.actions.run_and_verify_svn(None, None, [],
1408 'ci', '-m', 'log msg', sbox.wc_dir)
1411 prefix_url = sbox.repo_url + "/prefix_mydir"
1412 other_prefix_url = sbox.repo_url + "/prefix_other/mytag"
1413 svntest.actions.run_and_verify_svn(None, None, [],
1414 'cp', '-m', 'log msg', prefix_url,
1415 other_prefix_url)
1417 svntest.main.file_write(file_path, "Hello\nWorld\nIota\n")
1418 svntest.actions.run_and_verify_svn(None, None, [],
1419 'ci', '-m', 'log msg', prefix_path)
1421 out, err = svntest.actions.run_and_verify_svn(None, None, [],
1422 'diff', prefix_url,
1423 other_prefix_url)
1425 src = extract_diff_path(out[2])
1426 dest = extract_diff_path(out[3])
1428 good_src = ".../prefix_mydir"
1429 good_dest = ".../prefix_other/mytag"
1431 if ((src != good_src) or (dest != good_dest)):
1432 print("src is '%s' instead of '%s' and dest is '%s' instead of '%s'" %
1433 (src, good_src, dest, good_dest))
1434 raise svntest.Failure
1436 #----------------------------------------------------------------------
1437 def diff_renamed_file(sbox):
1438 "diff a file that has been renamed"
1440 sbox.build()
1442 os.chdir(sbox.wc_dir)
1444 pi_path = os.path.join('A', 'D', 'G', 'pi')
1445 pi2_path = os.path.join('A', 'D', 'pi2')
1446 svntest.main.file_write(pi_path, "new pi")
1448 svntest.actions.run_and_verify_svn(None, None, [],
1449 'ci', '-m', 'log msg')
1451 svntest.main.file_append(pi_path, "even more pi")
1453 svntest.actions.run_and_verify_svn(None, None, [],
1454 'ci', '-m', 'log msg')
1456 svntest.main.run_svn(None, 'mv', pi_path, pi2_path)
1458 # Repos->WC diff of the file
1459 diff_output, err_output = svntest.main.run_svn(None,
1460 'diff', '-r', '1',
1461 pi2_path)
1463 if check_diff_output(diff_output,
1464 pi2_path,
1465 'M') :
1466 raise svntest.Failure
1468 svntest.main.file_append(pi2_path, "new pi")
1470 # Repos->WC of the directory
1471 diff_output, err_output = svntest.main.run_svn(None,
1472 'diff', '-r', '1',
1473 os.path.join('A', 'D'))
1475 if check_diff_output(diff_output,
1476 pi_path,
1477 'D') :
1478 raise svntest.Failure
1480 if check_diff_output(diff_output,
1481 pi2_path,
1482 'M') :
1483 raise svntest.Failure
1485 # WC->WC of the file
1486 diff_output, err_output = svntest.main.run_svn(None, 'diff',
1487 pi2_path)
1488 if check_diff_output(diff_output,
1489 pi2_path,
1490 'M') :
1491 raise svntest.Failure
1494 svntest.actions.run_and_verify_svn(None, None, [],
1495 'ci', '-m', 'log msg')
1497 # Repos->WC diff of file after the rename.
1498 diff_output, err_output = svntest.main.run_svn(None,
1499 'diff', '-r', '1',
1500 pi2_path)
1501 if check_diff_output(diff_output,
1502 pi2_path,
1503 'M') :
1504 raise svntest.Failure
1506 # Repos->repos diff after the rename.
1507 diff_output, err_output = svntest.main.run_svn(None,
1508 'diff', '-r', '2:3',
1509 pi2_path)
1510 if check_diff_output(diff_output,
1511 os.path.join('A', 'D', 'pi'),
1512 'M') :
1513 raise svntest.Failure
1515 #----------------------------------------------------------------------
1516 def diff_within_renamed_dir(sbox):
1517 "diff a file within a renamed directory"
1519 sbox.build()
1521 os.chdir(sbox.wc_dir)
1523 svntest.main.run_svn(None, 'mv', os.path.join('A', 'D', 'G'),
1524 os.path.join('A', 'D', 'I'))
1525 # svntest.main.run_svn(None, 'ci', '-m', 'log_msg')
1526 svntest.main.file_write(os.path.join('A', 'D', 'I', 'pi'), "new pi")
1528 # Check a repos->wc diff
1529 diff_output, err_output = svntest.main.run_svn(None,
1530 'diff',
1531 os.path.join('A', 'D', 'I', 'pi'))
1532 if check_diff_output(diff_output,
1533 os.path.join('A', 'D', 'I', 'pi'),
1534 'M') :
1535 raise svntest.Failure
1537 svntest.actions.run_and_verify_svn(None, None, [],
1538 'ci', '-m', 'log msg')
1540 # Check repos->wc after commit
1541 diff_output, err_output = svntest.main.run_svn(None,
1542 'diff', '-r', '1',
1543 os.path.join('A', 'D', 'I', 'pi'))
1544 if check_diff_output(diff_output,
1545 os.path.join('A', 'D', 'I', 'pi'),
1546 'M') :
1547 raise svntest.Failure
1549 # Test the diff while within the moved directory
1550 os.chdir(os.path.join('A','D','I'))
1552 diff_output, err_output = svntest.main.run_svn(None,
1553 'diff', '-r', '1')
1555 if check_diff_output(diff_output, 'pi', 'M') :
1556 raise svntest.Failure
1558 # Test a repos->repos diff while within the moved directory
1559 diff_output, err_output = svntest.main.run_svn(None,
1560 'diff', '-r', '1:2')
1562 if check_diff_output(diff_output, 'pi', 'M') :
1563 raise svntest.Failure
1565 #----------------------------------------------------------------------
1566 def diff_prop_on_named_dir(sbox):
1567 "diff a prop change on a dir named explicitly"
1569 # Diff of a property change or addition should contain a "+" line.
1570 # Diff of a property change or deletion should contain a "-" line.
1571 # On a diff between repository revisions (not WC) of a dir named
1572 # explicitly, the "-" line was missing. (For a file, and for a dir
1573 # recursed into, the result was correct.)
1575 sbox.build()
1576 wc_dir = sbox.wc_dir
1578 os.chdir(sbox.wc_dir)
1580 svntest.actions.run_and_verify_svn(None, None, [],
1581 'propset', 'p', 'v', 'A')
1582 svntest.actions.run_and_verify_svn(None, None, [],
1583 'ci', '-m', '')
1585 svntest.actions.run_and_verify_svn(None, None, [],
1586 'propdel', 'p', 'A')
1587 svntest.actions.run_and_verify_svn(None, None, [],
1588 'ci', '-m', '')
1590 diff_output, err_output = svntest.main.run_svn(None,
1591 'diff', '-r2:3', 'A')
1592 # Check that the result contains a "-" line.
1593 verify_expected_output(diff_output, " - v")
1595 #----------------------------------------------------------------------
1596 def diff_keywords(sbox):
1597 "ensure that diff won't show keywords"
1599 sbox.build()
1601 iota_path = os.path.join(sbox.wc_dir, 'iota')
1603 svntest.actions.run_and_verify_svn(None, None, [],
1604 'ps',
1605 'svn:keywords',
1606 'Id Rev Date',
1607 iota_path)
1609 fp = open(iota_path, 'w')
1610 fp.write("$Date$\n")
1611 fp.write("$Id$\n")
1612 fp.write("$Rev$\n")
1613 fp.write("$Date::%s$\n" % (' ' * 80))
1614 fp.write("$Id::%s$\n" % (' ' * 80))
1615 fp.write("$Rev::%s$\n" % (' ' * 80))
1616 fp.close()
1618 svntest.actions.run_and_verify_svn(None, None, [],
1619 'ci', '-m', 'keywords', sbox.wc_dir)
1621 svntest.main.file_append(iota_path, "bar\n")
1622 svntest.actions.run_and_verify_svn(None, None, [],
1623 'ci', '-m', 'added bar', sbox.wc_dir)
1625 svntest.actions.run_and_verify_svn(None, None, [],
1626 'up', sbox.wc_dir)
1628 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1629 'diff',
1630 '-r', 'prev:head',
1631 sbox.wc_dir)
1632 verify_expected_output(diff_output, "+bar")
1633 verify_excluded_output(diff_output, "$Date:")
1634 verify_excluded_output(diff_output, "$Rev:")
1635 verify_excluded_output(diff_output, "$Id:")
1637 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1638 'diff',
1639 '-r', 'head:prev',
1640 sbox.wc_dir)
1641 verify_expected_output(diff_output, "-bar")
1642 verify_excluded_output(diff_output, "$Date:")
1643 verify_excluded_output(diff_output, "$Rev:")
1644 verify_excluded_output(diff_output, "$Id:")
1646 # Check fixed length keywords will show up
1647 # when the length of keyword has changed
1648 fp = open(iota_path, 'w')
1649 fp.write("$Date$\n")
1650 fp.write("$Id$\n")
1651 fp.write("$Rev$\n")
1652 fp.write("$Date::%s$\n" % (' ' * 79))
1653 fp.write("$Id::%s$\n" % (' ' * 79))
1654 fp.write("$Rev::%s$\n" % (' ' * 79))
1655 fp.close()
1657 svntest.actions.run_and_verify_svn(None, None, [],
1658 'ci', '-m', 'keywords 2', sbox.wc_dir)
1659 svntest.actions.run_and_verify_svn(None, None, [],
1660 'up', sbox.wc_dir)
1662 diff_output, err = svntest.actions.run_and_verify_svn(None, None, [],
1663 'diff',
1664 '-r', 'prev:head',
1665 sbox.wc_dir)
1666 # these should show up
1667 verify_expected_output(diff_output, "+$Id:: ")
1668 verify_expected_output(diff_output, "-$Id:: ")
1669 verify_expected_output(diff_output, "-$Rev:: ")
1670 verify_expected_output(diff_output, "+$Rev:: ")
1671 verify_expected_output(diff_output, "-$Date:: ")
1672 verify_expected_output(diff_output, "+$Date:: ")
1673 # ... and these won't
1674 verify_excluded_output(diff_output, "$Date: ")
1675 verify_excluded_output(diff_output, "$Rev: ")
1676 verify_excluded_output(diff_output, "$Id: ")
1679 def diff_force(sbox):
1680 "show diffs for binary files with --force"
1682 sbox.build()
1683 wc_dir = sbox.wc_dir
1685 iota_path = os.path.join(wc_dir, 'iota')
1687 # Append a line to iota and make it binary.
1688 svntest.main.file_append(iota_path, "new line")
1689 svntest.main.run_svn(None,
1690 'propset', 'svn:mime-type',
1691 'application/octet-stream', iota_path)
1693 # Created expected output tree for 'svn ci'
1694 expected_output = svntest.wc.State(wc_dir, {
1695 'iota' : Item(verb='Sending'),
1698 # Create expected status tree
1699 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1700 expected_status.add({
1701 'iota' : Item(status=' ', wc_rev=2),
1704 # Commit iota, creating revision 2.
1705 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1706 expected_status, None, wc_dir)
1708 # Add another line, while keeping he file as binary.
1709 svntest.main.file_append(iota_path, "another line")
1711 # Commit creating rev 3.
1712 expected_output = svntest.wc.State(wc_dir, {
1713 'iota' : Item(verb='Sending'),
1716 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
1717 expected_status.add({
1718 'iota' : Item(status=' ', wc_rev=3),
1721 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
1722 expected_status, None, wc_dir)
1724 # Check that we get diff when the first, the second and both files are
1725 # marked as binary.
1727 re_nodisplay = re.compile('^Cannot display:')
1729 stdout, stderr = svntest.main.run_svn(None,
1730 'diff', '-r1:2', iota_path,
1731 '--force')
1733 for line in stdout:
1734 if (re_nodisplay.match(line)):
1735 raise svntest.Failure
1737 stdout, stderr = svntest.main.run_svn(None,
1738 'diff', '-r2:1', iota_path,
1739 '--force')
1741 for line in stdout:
1742 if (re_nodisplay.match(line)):
1743 raise svntest.Failure
1745 stdout, stderr = svntest.main.run_svn(None,
1746 'diff', '-r2:3', iota_path,
1747 '--force')
1749 for line in stdout:
1750 if (re_nodisplay.match(line)):
1751 raise svntest.Failure
1753 #----------------------------------------------------------------------
1754 # Regression test for issue #2333: Renaming a directory should produce
1755 # deletion and addition diffs for each included file.
1756 def diff_renamed_dir(sbox):
1757 "diff a renamed directory"
1759 sbox.build()
1761 os.chdir(sbox.wc_dir)
1763 svntest.main.run_svn(None, 'mv', os.path.join('A', 'D', 'G'),
1764 os.path.join('A', 'D', 'I'))
1766 # Check a repos->wc diff
1767 diff_output, err_output = svntest.main.run_svn(None, 'diff',
1768 os.path.join('A', 'D'))
1769 if check_diff_output(diff_output,
1770 os.path.join('A', 'D', 'G', 'pi'),
1771 'D') :
1772 raise svntest.Failure
1773 if check_diff_output(diff_output,
1774 os.path.join('A', 'D', 'I', 'pi'),
1775 'A') :
1776 raise svntest.Failure
1778 svntest.actions.run_and_verify_svn(None, None, [],
1779 'ci', '-m', 'log msg')
1781 # Check repos->wc after commit
1782 diff_output, err_output = svntest.main.run_svn(None,
1783 'diff', '-r', '1',
1784 os.path.join('A', 'D'))
1785 if check_diff_output(diff_output,
1786 os.path.join('A', 'D', 'G', 'pi'),
1787 'D') :
1788 raise svntest.Failure
1789 if check_diff_output(diff_output,
1790 os.path.join('A', 'D', 'I', 'pi'),
1791 'A') :
1792 raise svntest.Failure
1794 # Test a repos->repos diff after commit
1795 diff_output, err_output = svntest.main.run_svn(None,
1796 'diff', '-r', '1:2')
1797 if check_diff_output(diff_output,
1798 os.path.join('A', 'D', 'G', 'pi'),
1799 'D') :
1800 raise svntest.Failure
1801 if check_diff_output(diff_output,
1802 os.path.join('A', 'D', 'I', 'pi'),
1803 'A') :
1804 raise svntest.Failure
1806 # Test the diff while within the moved directory
1807 os.chdir(os.path.join('A','D','I'))
1809 diff_output, err_output = svntest.main.run_svn(None,
1810 'diff', '-r', '1')
1812 if check_diff_output(diff_output, 'pi', 'A') :
1813 raise svntest.Failure
1815 # Test a repos->repos diff while within the moved directory
1816 diff_output, err_output = svntest.main.run_svn(None,
1817 'diff', '-r', '1:2')
1819 if check_diff_output(diff_output, 'pi', 'A') :
1820 raise svntest.Failure
1823 #----------------------------------------------------------------------
1824 def diff_property_changes_to_base(sbox):
1825 "diff to BASE with local property mods"
1827 sbox.build()
1828 wc_dir = sbox.wc_dir
1830 expected_output_r1_r2 = [
1831 "\n",
1832 "Property changes on: A\n",
1833 "___________________________________________________________________\n",
1834 "Added: dirprop\n",
1835 " + r2value\n",
1836 "\n",
1837 "\n",
1838 "Property changes on: iota\n",
1839 "___________________________________________________________________\n",
1840 "Added: fileprop\n",
1841 " + r2value\n",
1842 "\n" ]
1844 expected_output_r2_r1 = list(expected_output_r1_r2)
1845 expected_output_r2_r1[3] = expected_output_r2_r1[3].replace("Added",
1846 "Deleted")
1847 expected_output_r2_r1[4] = " - r2value\n"
1848 expected_output_r2_r1[9] = expected_output_r2_r1[9].replace("Added",
1849 "Deleted")
1850 expected_output_r2_r1[10] = " - r2value\n"
1853 os.chdir(sbox.wc_dir)
1855 svntest.actions.run_and_verify_svn(None, None, [],
1856 'propset',
1857 'fileprop', 'r2value', 'iota')
1859 svntest.actions.run_and_verify_svn(None, None, [],
1860 'propset',
1861 'dirprop', 'r2value', 'A')
1863 svntest.actions.run_and_verify_svn(None, None, [],
1864 'ci', '-m', 'empty-msg')
1866 # Check that forward and reverse repos-repos diffs are as expected.
1867 expected = svntest.verify.UnorderedOutput(expected_output_r1_r2)
1868 svntest.actions.run_and_verify_svn(None, expected, [],
1869 'diff', '-r', '1:2')
1871 expected = svntest.verify.UnorderedOutput(expected_output_r2_r1)
1872 svntest.actions.run_and_verify_svn(None, expected, [],
1873 'diff', '-r', '2:1')
1875 # Now check repos->WORKING, repos->BASE, and BASE->repos.
1876 # (BASE is r1, and WORKING has no local mods, so this should produce
1877 # the same output as above).
1878 expected = svntest.verify.UnorderedOutput(expected_output_r1_r2)
1879 svntest.actions.run_and_verify_svn(None, expected, [],
1880 'diff', '-r', '1')
1882 svntest.actions.run_and_verify_svn(None, expected, [],
1883 'diff', '-r', '1:BASE')
1885 expected = svntest.verify.UnorderedOutput(expected_output_r2_r1)
1886 svntest.actions.run_and_verify_svn(None, expected, [],
1887 'diff', '-r', 'BASE:1')
1889 # Modify some properties.
1890 svntest.actions.run_and_verify_svn(None, None, [],
1891 'propset',
1892 'fileprop', 'workingvalue', 'iota')
1894 svntest.actions.run_and_verify_svn(None, None, [],
1895 'propset',
1896 'dirprop', 'workingvalue', 'A')
1898 svntest.actions.run_and_verify_svn(None, None, [],
1899 'propset',
1900 'fileprop', 'workingvalue', 'A/mu')
1902 # Check that the earlier diffs against BASE are unaffected by the
1903 # presence of local mods.
1904 expected = svntest.verify.UnorderedOutput(expected_output_r1_r2)
1905 svntest.actions.run_and_verify_svn(None, expected, [],
1906 'diff', '-r', '1:BASE')
1908 expected = svntest.verify.UnorderedOutput(expected_output_r2_r1)
1909 svntest.actions.run_and_verify_svn(None, expected, [],
1910 'diff', '-r', 'BASE:1')
1912 def diff_schedule_delete(sbox):
1913 "scheduled deleted"
1915 sbox.build()
1917 expected_output_r2_working = [
1918 "Index: foo\n",
1919 "===================================================================\n",
1920 "--- foo\t(revision 2)\n",
1921 "+++ foo\t(working copy)\n",
1922 "@@ -1 +0,0 @@\n",
1923 "-xxx\n"
1926 expected_output_r2_base = [
1927 "Index: foo\n",
1928 "===================================================================\n",
1929 "--- foo\t(revision 2)\n",
1930 "+++ foo\t(working copy)\n",
1931 "@@ -1 +1,2 @@\n",
1932 " xxx\n",
1933 "+yyy\n"
1935 expected_output_base_r2 = [
1936 "Index: foo\n",
1937 "===================================================================\n",
1938 "--- foo\t(working copy)\n",
1939 "+++ foo\t(revision 2)\n",
1940 "@@ -1,2 +1 @@\n",
1941 " xxx\n",
1942 "-yyy\n"
1945 expected_output_r1_base = [
1946 "Index: foo\n",
1947 "===================================================================\n",
1948 "--- foo\t(revision 0)\n",
1949 "+++ foo\t(revision 3)\n",
1950 "@@ -0,0 +1,2 @@\n",
1951 "+xxx\n",
1952 "+yyy\n"
1954 expected_output_base_r1 = [
1955 "Index: foo\n",
1956 "===================================================================\n",
1957 "--- foo\t(working copy)\n",
1958 "+++ foo\t(revision 1)\n",
1959 "@@ -1,2 +0,0 @@\n",
1960 "-xxx\n",
1961 "-yyy\n"
1963 expected_output_base_working = expected_output_base_r1[:]
1964 expected_output_base_working[2] = "--- foo\t(revision 3)\n"
1965 expected_output_base_working[3] = "+++ foo\t(working copy)\n"
1967 wc_dir = sbox.wc_dir
1968 os.chdir(wc_dir)
1970 svntest.main.file_append('foo', "xxx\n")
1971 svntest.main.run_svn(None, 'add', 'foo')
1972 svntest.main.run_svn(None,
1973 'ci', '-m', 'log msg r2')
1975 svntest.main.file_append('foo', "yyy\n")
1976 svntest.main.run_svn(None,
1977 'ci', '-m', 'log msg r3')
1979 # Update everyone's BASE to r3, and mark 'foo' as schedule-deleted.
1980 svntest.main.run_svn(None,
1981 'up')
1982 svntest.main.run_svn(None, 'rm', 'foo')
1984 # A file marked as schedule-delete should act as if were not present
1985 # in WORKING, but diffs against BASE should remain unaffected.
1987 # 1. repos-wc diff: file not present in repos.
1988 svntest.actions.run_and_verify_svn(None, [], [],
1989 'diff', '-r', '1')
1990 svntest.actions.run_and_verify_svn(None, expected_output_r1_base, [],
1991 'diff', '-r', '1:BASE')
1992 svntest.actions.run_and_verify_svn(None, expected_output_base_r1, [],
1993 'diff', '-r', 'BASE:1')
1995 # 2. repos-wc diff: file present in repos.
1996 svntest.actions.run_and_verify_svn(None, expected_output_r2_working, [],
1997 'diff', '-r', '2')
1998 svntest.actions.run_and_verify_svn(None, expected_output_r2_base, [],
1999 'diff', '-r', '2:BASE')
2000 svntest.actions.run_and_verify_svn(None, expected_output_base_r2, [],
2001 'diff', '-r', 'BASE:2')
2003 # 3. wc-wc diff.
2004 svntest.actions.run_and_verify_svn(None, expected_output_base_working, [],
2005 'diff')
2007 #----------------------------------------------------------------------
2008 def diff_mime_type_changes(sbox):
2009 "repos-wc diffs with local svn:mime-type prop mods"
2011 sbox.build()
2013 expected_output_r1_wc = [
2014 "Index: iota\n",
2015 "===================================================================\n",
2016 "--- iota\t(revision 1)\n",
2017 "+++ iota\t(working copy)\n",
2018 "@@ -1 +1,2 @@\n",
2019 " This is the file 'iota'.\n",
2020 "+revision 2 text.\n" ]
2022 expected_output_wc_r1 = [
2023 "Index: iota\n",
2024 "===================================================================\n",
2025 "--- iota\t(working copy)\n",
2026 "+++ iota\t(revision 1)\n",
2027 "@@ -1,2 +1 @@\n",
2028 " This is the file 'iota'.\n",
2029 "-revision 2 text.\n" ]
2032 os.chdir(sbox.wc_dir)
2034 # Append some text to iota (r2).
2035 svntest.main.file_append('iota', "revision 2 text.\n")
2037 svntest.actions.run_and_verify_svn(None, None, [],
2038 'ci', '-m', 'log_msg')
2040 # Check that forward and reverse repos-BASE diffs are as expected.
2041 svntest.actions.run_and_verify_svn(None, expected_output_r1_wc, [],
2042 'diff', '-r', '1:BASE')
2044 svntest.actions.run_and_verify_svn(None, expected_output_wc_r1, [],
2045 'diff', '-r', 'BASE:1')
2047 # Mark iota as a binary file in the working copy.
2048 svntest.actions.run_and_verify_svn(None, None, [],
2049 'propset', 'svn:mime-type',
2050 'application/octet-stream', 'iota')
2052 # Check that the earlier diffs against BASE are unaffected by the
2053 # presence of local svn:mime-type property mods.
2054 svntest.actions.run_and_verify_svn(None, expected_output_r1_wc, [],
2055 'diff', '-r', '1:BASE')
2057 svntest.actions.run_and_verify_svn(None, expected_output_wc_r1, [],
2058 'diff', '-r', 'BASE:1')
2060 # Commit the change (r3) (so that BASE has the binary MIME type), then
2061 # mark iota as a text file again in the working copy.
2062 svntest.actions.run_and_verify_svn(None, None, [],
2063 'ci', '-m', 'log_msg')
2064 svntest.actions.run_and_verify_svn(None, None, [],
2065 'propdel', 'svn:mime-type', 'iota')
2067 # Now diffs against BASE will fail, but diffs against WORKNG should be
2068 # fine.
2069 svntest.actions.run_and_verify_svn(None, expected_output_r1_wc, [],
2070 'diff', '-r', '1')
2073 #----------------------------------------------------------------------
2074 # Test a repos-WORKING diff, with different versions of the same property
2075 # at repository, BASE, and WORKING.
2076 def diff_prop_change_local_propmod(sbox):
2077 "diff a property change plus a local prop edit"
2079 sbox.build()
2081 expected_output_r2_wc = [
2082 "\n",
2083 "Property changes on: A\n",
2084 "___________________________________________________________________\n",
2085 "Modified: dirprop\n",
2086 " - r2value\n",
2087 " + workingvalue\n",
2088 "Added: newdirprop\n",
2089 " + newworkingvalue\n",
2090 "\n",
2091 "\n",
2092 "Property changes on: iota\n",
2093 "___________________________________________________________________\n",
2094 "Modified: fileprop\n",
2095 " - r2value\n",
2096 " + workingvalue\n",
2097 "Added: newfileprop\n",
2098 " + newworkingvalue\n",
2099 "\n" ]
2101 os.chdir(sbox.wc_dir)
2103 # Set a property on A/ and iota, and commit them (r2).
2104 svntest.actions.run_and_verify_svn(None, None, [],
2105 'propset', 'dirprop',
2106 'r2value', 'A')
2107 svntest.actions.run_and_verify_svn(None, None, [],
2108 'propset', 'fileprop',
2109 'r2value', 'iota')
2110 svntest.actions.run_and_verify_svn(None, None, [],
2111 'ci', '-m', 'log_msg')
2113 # Change the property values on A/ and iota, and commit them (r3).
2114 svntest.actions.run_and_verify_svn(None, None, [],
2115 'propset', 'dirprop',
2116 'r3value', 'A')
2117 svntest.actions.run_and_verify_svn(None, None, [],
2118 'propset', 'fileprop',
2119 'r3value', 'iota')
2120 svntest.actions.run_and_verify_svn(None, None, [],
2121 'ci', '-m', 'log_msg')
2123 # Finally, change the property values one last time.
2124 svntest.actions.run_and_verify_svn(None, None, [],
2125 'propset', 'dirprop',
2126 'workingvalue', 'A')
2127 svntest.actions.run_and_verify_svn(None, None, [],
2128 'propset', 'fileprop',
2129 'workingvalue', 'iota')
2130 # And also add some properties that only exist in WORKING.
2131 svntest.actions.run_and_verify_svn(None, None, [],
2132 'propset', 'newdirprop',
2133 'newworkingvalue', 'A')
2134 svntest.actions.run_and_verify_svn(None, None, [],
2135 'propset', 'newfileprop',
2136 'newworkingvalue', 'iota')
2138 # Now, if we diff r2 to WORKING, we've got three property values
2139 # to consider: r2value (in the repository), r3value (in BASE), and
2140 # workingvalue (in WORKING).
2141 # The diff should only show the r2->WORKING change.
2143 # We also need to make sure that the 'new' (WORKING only) properties
2144 # are included in the output, since they won't be listed in a simple
2145 # BASE->r2 diff.
2146 expected = svntest.verify.UnorderedOutput(expected_output_r2_wc)
2147 svntest.actions.run_and_verify_svn(None, expected, [],
2148 'diff', '-r', '2')
2151 #----------------------------------------------------------------------
2152 # repos->wc and BASE->repos diffs that add files or directories with
2153 # properties should show the added properties.
2154 def diff_repos_wc_add_with_props(sbox):
2155 "repos-wc diff showing added entries with props"
2157 sbox.build()
2159 expected_output_r1_r3 = [
2160 "Index: foo\n",
2161 "===================================================================\n",
2162 "--- foo\t(revision 0)\n",
2163 "+++ foo\t(revision 3)\n",
2164 "@@ -0,0 +1 @@\n",
2165 "+content\n",
2166 "\n",
2167 "Property changes on: foo\n",
2168 "___________________________________________________________________\n",
2169 "Added: propname\n",
2170 " + propvalue\n",
2171 "\n",
2172 "\n",
2173 "Property changes on: X\n",
2174 "___________________________________________________________________\n",
2175 "Added: propname\n",
2176 " + propvalue\n",
2177 "\n",
2178 "Index: X/bar\n",
2179 "===================================================================\n",
2180 "--- X/bar\t(revision 0)\n",
2181 "+++ X/bar\t(revision 3)\n",
2182 "@@ -0,0 +1 @@\n",
2183 "+content\n",
2184 "\n",
2185 "Property changes on: " + os.path.join('X', 'bar') + "\n",
2186 "___________________________________________________________________\n",
2187 "Added: propname\n",
2188 " + propvalue\n",
2189 "\n" ]
2190 # The output from the BASE->repos diff is the same content, but in a
2191 # different order.
2192 expected_output_r1_r3_a = expected_output_r1_r3[:12] + \
2193 expected_output_r1_r3[18:] + expected_output_r1_r3[12:18]
2195 os.chdir(sbox.wc_dir)
2197 # Create directory X, file foo, and file X/bar, and commit them (r2).
2198 os.makedirs('X')
2199 svntest.main.file_append('foo', "content\n")
2200 svntest.main.file_append(os.path.join('X', 'bar'), "content\n")
2201 svntest.actions.run_and_verify_svn(None, None, [],
2202 'add', 'X', 'foo')
2203 svntest.actions.run_and_verify_svn(None, None, [],
2204 'ci', '-m', 'log_msg')
2206 # Set a property on all three items, and commit them (r3).
2207 svntest.actions.run_and_verify_svn(None, None, [],
2208 'propset', 'propname',
2209 'propvalue', 'X', 'foo',
2210 os.path.join('X', 'bar'))
2211 svntest.actions.run_and_verify_svn(None, None, [],
2212 'ci', '-m', 'log_msg')
2214 # Now, if we diff r1 to WORKING or BASE, we should see the content
2215 # addition for foo and X/bar, and property additions for all three.
2216 svntest.actions.run_and_verify_svn(None, expected_output_r1_r3, [],
2217 'diff', '-r', '1')
2218 svntest.actions.run_and_verify_svn(None, expected_output_r1_r3, [],
2219 'diff', '-r', '1:BASE')
2221 # Update the BASE and WORKING revisions to r1.
2222 svntest.actions.run_and_verify_svn(None, None, [],
2223 'up', '-r', '1')
2225 # If we diff BASE to r3, we should see the same output as above.
2226 svntest.actions.run_and_verify_svn(None, expected_output_r1_r3_a, [],
2227 'diff', '-r', 'BASE:3')
2230 #----------------------------------------------------------------------
2231 # repos-wc diffs on a non-recursively checked out wc that would normally
2232 # (if recursively checked out) include a directory that is not present in
2233 # the repos version should not segfault.
2234 def diff_nonrecursive_checkout_deleted_dir(sbox):
2235 "nonrecursive diff + deleted directories"
2236 sbox.build()
2238 url = sbox.repo_url
2239 A_url = url + '/A'
2240 A_prime_url = url + '/A_prime'
2242 svntest.main.run_svn(None,
2243 'cp', '-m', 'log msg', A_url, A_prime_url)
2245 svntest.main.run_svn(None,
2246 'mkdir', '-m', 'log msg', A_prime_url + '/Q')
2248 wc = sbox.add_wc_path('wc')
2250 svntest.main.run_svn(None,
2251 'co', '-N', A_prime_url, wc)
2253 os.chdir(wc)
2255 # We don't particular care about the output here, just that it doesn't
2256 # segfault.
2257 svntest.main.run_svn(None,
2258 'diff', '-r1')
2261 #----------------------------------------------------------------------
2262 # repos->WORKING diffs that include directories with local mods that are
2263 # not present in the repos version should work as expected (and not, for
2264 # example, show an extraneous BASE->WORKING diff for the added directory
2265 # after the repos->WORKING output).
2266 def diff_repos_working_added_dir(sbox):
2267 "repos->WORKING diff showing added modifed dir"
2269 sbox.build()
2271 expected_output_r1_BASE = [
2272 "Index: X/bar\n",
2273 "===================================================================\n",
2274 "--- X/bar\t(revision 0)\n",
2275 "+++ X/bar\t(revision 2)\n",
2276 "@@ -0,0 +1 @@\n",
2277 "+content\n" ]
2278 expected_output_r1_WORKING = [
2279 "Index: X/bar\n",
2280 "===================================================================\n",
2281 "--- X/bar\t(revision 0)\n",
2282 "+++ X/bar\t(revision 2)\n",
2283 "@@ -0,0 +1,2 @@\n",
2284 "+content\n",
2285 "+more content\n" ]
2287 os.chdir(sbox.wc_dir)
2289 # Create directory X and file X/bar, and commit them (r2).
2290 os.makedirs('X')
2291 svntest.main.file_append(os.path.join('X', 'bar'), "content\n")
2292 svntest.actions.run_and_verify_svn(None, None, [],
2293 'add', 'X')
2294 svntest.actions.run_and_verify_svn(None, None, [],
2295 'ci', '-m', 'log_msg')
2297 # Make a local modification to X/bar.
2298 svntest.main.file_append(os.path.join('X', 'bar'), "more content\n")
2300 # Now, if we diff r1 to WORKING or BASE, we should see the content
2301 # addition for X/bar, and (for WORKING) the local modification.
2302 svntest.actions.run_and_verify_svn(None, expected_output_r1_BASE, [],
2303 'diff', '-r', '1:BASE')
2304 svntest.actions.run_and_verify_svn(None, expected_output_r1_WORKING, [],
2305 'diff', '-r', '1')
2308 #----------------------------------------------------------------------
2309 # A base->repos diff of a moved file used to output an all-lines-deleted diff
2310 def diff_base_repos_moved(sbox):
2311 "base->repos diff of moved file"
2313 sbox.build()
2315 os.chdir(sbox.wc_dir)
2317 oldfile = 'iota'
2318 newfile = 'kappa'
2320 # Move, modify and commit a file
2321 svntest.main.run_svn(None, 'mv', oldfile, newfile)
2322 svntest.main.file_write(newfile, "new content\n")
2323 svntest.actions.run_and_verify_svn(None, None, [],
2324 'ci', '-m', '')
2326 # Check that a base->repos diff shows deleted and added lines.
2327 # It's not clear whether we expect a file-change diff or
2328 # a file-delete plus file-add. The former is currently produced if we
2329 # explicitly request a diff of the file itself, and the latter if we
2330 # request a tree diff which just happens to contain the file.
2331 out, err = svntest.actions.run_and_verify_svn(None,
2332 svntest.verify.AnyOutput, [],
2333 'diff', '-rBASE:1', newfile)
2334 if check_diff_output(out, newfile, 'M'):
2335 raise svntest.Failure
2337 # Diff should recognise that the item's name has changed, and mention both
2338 # the current and the old name in parentheses, in the right order.
2339 if (out[2][:3] != '---' or out[2].find('kappa)') == -1 or
2340 out[3][:3] != '+++' or out[3].find('iota)') == -1):
2341 raise svntest.Failure
2344 #----------------------------------------------------------------------
2345 # A diff of an added file within an added directory should work, and
2346 # shouldn't produce an error.
2347 def diff_added_subtree(sbox):
2348 "wc->repos diff of added subtree"
2350 sbox.build()
2352 os.chdir(sbox.wc_dir)
2354 # Roll the wc back to r0 (i.e. an empty wc).
2355 svntest.actions.run_and_verify_svn(None, None, [],
2356 'up', '-r0')
2358 # We shouldn't get any errors when we request a diff showing the
2359 # addition of the greek tree. The diff contains additions of files
2360 # and directories with parents that don't currently exist in the wc,
2361 # which is what we're testing here.
2362 svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, [],
2363 'diff', '-r', 'BASE:1')
2365 #----------------------------------------------------------------------
2366 def basic_diff_summarize(sbox):
2367 "basic diff summarize"
2369 sbox.build()
2370 wc_dir = sbox.wc_dir
2372 # A content modification.
2373 svntest.main.file_append(os.path.join(wc_dir, "A", "mu"), "New mu content")
2375 # A prop modification.
2376 svntest.main.run_svn(None,
2377 "propset", "prop", "val",
2378 os.path.join(wc_dir, 'iota'))
2380 # Both content and prop mods.
2381 tau_path = os.path.join(wc_dir, "A", "D", "G", "tau")
2382 svntest.main.file_append(tau_path, "tautau")
2383 svntest.main.run_svn(None,
2384 "propset", "prop", "val", tau_path)
2386 # A file addition.
2387 newfile_path = os.path.join(wc_dir, 'newfile')
2388 svntest.main.file_append(newfile_path, 'newfile')
2389 svntest.main.run_svn(None, 'add', newfile_path)
2391 # A file deletion.
2392 svntest.main.run_svn(None, "delete", os.path.join(wc_dir, 'A', 'B',
2393 'lambda'))
2395 expected_output = svntest.wc.State(wc_dir, {
2396 'A/mu': Item(verb='Sending'),
2397 'iota': Item(verb='Sending'),
2398 'newfile': Item(verb='Adding'),
2399 'A/D/G/tau': Item(verb='Sending'),
2400 'A/B/lambda': Item(verb='Deleting'),
2402 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2403 expected_status.add({
2404 'newfile': Item(status=' ', wc_rev=2),
2406 expected_status.tweak("A/mu", "iota", "A/D/G/tau", 'newfile', wc_rev=2)
2407 expected_status.remove("A/B/lambda")
2409 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2410 expected_status, None, wc_dir)
2412 # Get the differences between two versions of a file.
2413 expected_diff = svntest.wc.State(wc_dir, {
2414 'iota': Item(status=' M'),
2416 svntest.actions.run_and_verify_diff_summarize(expected_diff, None,
2417 None, None, None, None,
2418 os.path.join(wc_dir, 'iota'),
2419 '-c2')
2421 # Get the differences between two versions of an entire directory.
2422 expected_diff = svntest.wc.State(wc_dir, {
2423 'A/mu': Item(status='M '),
2424 'iota': Item(status=' M'),
2425 'A/D/G/tau': Item(status='MM'),
2426 'newfile': Item(status='A '),
2427 'A/B/lambda': Item(status='D '),
2429 svntest.actions.run_and_verify_diff_summarize(expected_diff, None,
2430 None, None, None, None,
2431 wc_dir, '-r1:2')
2433 def diff_weird_author(sbox):
2434 "diff with svn:author that has < in it"
2436 sbox.build()
2438 svntest.actions.enable_revprop_changes(sbox.repo_dir)
2440 svntest.main.file_write(os.path.join(sbox.wc_dir, 'A', 'mu'),
2441 "new content\n")
2443 expected_output = svntest.wc.State(sbox.wc_dir, {
2444 'A/mu': Item(verb='Sending'),
2447 expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
2448 expected_status.tweak("A/mu", wc_rev=2)
2450 svntest.actions.run_and_verify_commit(sbox.wc_dir, expected_output,
2451 expected_status, None, sbox.wc_dir)
2453 svntest.main.run_svn(None,
2454 "propset", "--revprop", "-r", "2", "svn:author",
2455 "J. Random <jrandom@example.com>", sbox.repo_url)
2457 svntest.actions.run_and_verify_svn(None,
2458 ["J. Random <jrandom@example.com>\n"],
2460 "pget", "--revprop", "-r" "2",
2461 "svn:author", sbox.repo_url)
2463 expected_output = [
2464 "Index: A/mu\n",
2465 "===================================================================\n",
2466 "--- A/mu\t(revision 1)\n",
2467 "+++ A/mu\t(revision 2)\n",
2468 "@@ -1 +1 @@\n",
2469 "-This is the file 'mu'.\n",
2470 "+new content\n"
2473 svntest.actions.run_and_verify_svn(None, expected_output, [],
2474 'diff', '-r1:2', sbox.repo_url)
2476 # test for issue 2121, use -x -w option for ignoring whitespace during diff
2477 def diff_ignore_whitespace(sbox):
2478 "ignore whitespace when diffing"
2480 sbox.build()
2481 wc_dir = sbox.wc_dir
2483 file_name = "iota"
2484 file_path = os.path.join(wc_dir, file_name)
2486 svntest.main.file_write(file_path,
2487 "Aa\n"
2488 "Bb\n"
2489 "Cc\n")
2490 expected_output = svntest.wc.State(wc_dir, {
2491 'iota' : Item(verb='Sending'),
2493 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2494 None, None, wc_dir)
2496 # only whitespace changes, should return no changes
2497 svntest.main.file_write(file_path,
2498 " A a \n"
2499 " B b \n"
2500 " C c \n")
2502 svntest.actions.run_and_verify_svn(None, [], [],
2503 'diff', '-x', '-w', file_path)
2505 # some changes + whitespace
2506 svntest.main.file_write(file_path,
2507 " A a \n"
2508 "Xxxx X\n"
2509 " Bb b \n"
2510 " C c \n")
2511 expected_output = [
2512 "Index: svn-test-work/working_copies/diff_tests-39/iota\n",
2513 "===================================================================\n",
2514 "--- svn-test-work/working_copies/diff_tests-39/iota\t(revision 2)\n",
2515 "+++ svn-test-work/working_copies/diff_tests-39/iota\t(working copy)\n",
2516 "@@ -1,3 +1,4 @@\n",
2517 " Aa\n",
2518 "-Bb\n",
2519 "+Xxxx X\n",
2520 "+ Bb b \n",
2521 " Cc\n" ]
2523 svntest.actions.run_and_verify_svn(None, expected_output, [],
2524 'diff', '-x', '-w', file_path)
2526 def diff_ignore_eolstyle(sbox):
2527 "ignore eol styles when diffing"
2529 sbox.build()
2530 wc_dir = sbox.wc_dir
2532 file_name = "iota"
2533 file_path = os.path.join(wc_dir, file_name)
2535 svntest.main.file_write(file_path,
2536 "Aa\n"
2537 "Bb\n"
2538 "Cc\n")
2539 expected_output = svntest.wc.State(wc_dir, {
2540 'iota' : Item(verb='Sending'),
2542 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2543 None, None, wc_dir)
2545 # commit only eol changes
2546 svntest.main.file_write(file_path,
2547 "Aa\r"
2548 "Bb\r"
2549 "Cc")
2551 expected_output = [
2552 "Index: svn-test-work/working_copies/diff_tests-40/iota\n",
2553 "===================================================================\n",
2554 "--- svn-test-work/working_copies/diff_tests-40/iota\t(revision 2)\n",
2555 "+++ svn-test-work/working_copies/diff_tests-40/iota\t(working copy)\n",
2556 "@@ -1,3 +1,3 @@\n",
2557 " Aa\n",
2558 " Bb\n",
2559 "-Cc\n",
2560 "+Cc\n",
2561 "\ No newline at end of file\n" ]
2563 svntest.actions.run_and_verify_svn(None, expected_output, [],
2564 'diff', '-x', '--ignore-eol-style',
2565 file_path)
2567 # test for issue 2600, diff revision of a file in a renamed folder
2568 def diff_in_renamed_folder(sbox):
2569 "diff a revision of a file in a renamed folder"
2571 sbox.build()
2572 wc_dir = sbox.wc_dir
2574 C_path = os.path.join(wc_dir, "A", "C")
2575 D_path = os.path.join(wc_dir, "A", "D")
2576 kappa_path = os.path.join(D_path, "C", "kappa")
2578 # add a new file to a renamed (moved in this case) folder.
2579 svntest.main.run_svn(None, 'mv', C_path, D_path)
2581 svntest.main.file_append(kappa_path, "this is file kappa.\n")
2582 svntest.main.run_svn(None, 'add', kappa_path)
2584 expected_output = svntest.wc.State(wc_dir, {
2585 'A/C' : Item(verb='Deleting'),
2586 'A/D/C' : Item(verb='Adding'),
2587 'A/D/C/kappa' : Item(verb='Adding'),
2589 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2590 None, None, wc_dir)
2592 expected_output = svntest.wc.State(wc_dir, {
2593 'A/D/C/kappa' : Item(verb='Sending'),
2596 # modify the file two times so we have something to diff.
2597 for i in range(3, 5):
2598 svntest.main.file_append(kappa_path, str(i) + "\n")
2599 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2600 None, None, wc_dir)
2602 expected_output = [
2603 "Index: svn-test-work/working_copies/diff_tests-41/A/D/C/kappa\n",
2604 "===================================================================\n",
2605 "--- svn-test-work/working_copies/diff_tests-41/A/D/C/kappa\t(revision 3)\n",
2606 "+++ svn-test-work/working_copies/diff_tests-41/A/D/C/kappa\t(revision 4)\n",
2607 "@@ -1,2 +1,3 @@\n",
2608 " this is file kappa.\n",
2609 " 3\n",
2610 "+4\n"
2613 svntest.actions.run_and_verify_svn(None, expected_output, [],
2614 'diff', '-r3:4', kappa_path)
2616 def diff_with_depth(sbox):
2617 "test diffs at various depths"
2619 sbox.build()
2621 diff = [
2622 "\n",
2623 "Property changes on: .\n",
2624 "___________________________________________________________________\n",
2625 "Added: foo1\n",
2626 " + bar1\n",
2627 "\n",
2628 "\n",
2629 "Property changes on: iota\n",
2630 "___________________________________________________________________\n",
2631 "Added: foo2\n",
2632 " + bar2\n",
2633 "\n",
2634 "\n",
2635 "Property changes on: A\n",
2636 "___________________________________________________________________\n",
2637 "Added: foo3\n",
2638 " + bar3\n",
2639 "\n",
2640 "\n",
2641 "Property changes on: " + os.path.join('A', 'B') + "\n",
2642 "___________________________________________________________________\n",
2643 "Added: foo4\n",
2644 " + bar4\n",
2645 "\n" ]
2647 expected_empty = svntest.verify.UnorderedOutput(diff[:6])
2648 expected_files = svntest.verify.UnorderedOutput(diff[:12])
2649 expected_immediates = svntest.verify.UnorderedOutput(diff[:18])
2650 expected_infinity = svntest.verify.UnorderedOutput(diff[:])
2652 os.chdir(sbox.wc_dir)
2654 svntest.actions.run_and_verify_svn(None, None, [],
2655 'propset',
2656 'foo1', 'bar1', '.')
2657 svntest.actions.run_and_verify_svn(None, None, [],
2658 'propset',
2659 'foo2', 'bar2', 'iota')
2660 svntest.actions.run_and_verify_svn(None, None, [],
2661 'propset',
2662 'foo3', 'bar3', 'A')
2663 svntest.actions.run_and_verify_svn(None, None, [],
2664 'propset',
2665 'foo4', 'bar4', os.path.join('A', 'B'))
2667 # Test wc-wc diff.
2668 svntest.actions.run_and_verify_svn(None, expected_empty, [],
2669 'diff', '--depth', 'empty')
2670 svntest.actions.run_and_verify_svn(None, expected_files, [],
2671 'diff', '--depth', 'files')
2672 svntest.actions.run_and_verify_svn(None, expected_immediates, [],
2673 'diff', '--depth', 'immediates')
2674 svntest.actions.run_and_verify_svn(None, expected_infinity, [],
2675 'diff', '--depth', 'infinity')
2677 # Commit the changes.
2678 svntest.actions.run_and_verify_svn(None, None, [],
2679 'ci', '-m', '')
2681 # Test repos-repos diff. Reuse the expected outputs from above.
2682 svntest.actions.run_and_verify_svn(None, expected_empty, [],
2683 'diff', '-c2', '--depth', 'empty')
2684 svntest.actions.run_and_verify_svn(None, expected_files, [],
2685 'diff', '-c2', '--depth', 'files')
2686 svntest.actions.run_and_verify_svn(None, expected_immediates, [],
2687 'diff', '-c2', '--depth', 'immediates')
2688 svntest.actions.run_and_verify_svn(None, expected_infinity, [],
2689 'diff', '-c2', '--depth', 'infinity')
2691 diff_wc_repos = [
2692 "\n",
2693 "Property changes on: .\n",
2694 "___________________________________________________________________\n",
2695 "Modified: foo1\n",
2696 " - bar1\n",
2697 " + baz1\n",
2698 "\n",
2699 "\n",
2700 "Property changes on: iota\n",
2701 "___________________________________________________________________\n",
2702 "Modified: foo2\n",
2703 " - bar2\n",
2704 " + baz2\n",
2705 "\n",
2706 "\n",
2707 "Index: iota\n",
2708 "===================================================================\n",
2709 "--- iota\t(revision 2)\n",
2710 "+++ iota\t(working copy)\n",
2711 "@@ -1 +1,2 @@\n",
2712 " This is the file 'iota'.\n",
2713 "+new text\n",
2714 "Property changes on: A\n",
2715 "___________________________________________________________________\n",
2716 "Modified: foo3\n",
2717 " - bar3\n",
2718 " + baz3\n",
2719 "\n",
2720 "\n",
2721 "Property changes on: " + os.path.join('A', 'B') + "\n",
2722 "___________________________________________________________________\n",
2723 "Modified: foo4\n",
2724 " - bar4\n",
2725 " + baz4\n",
2726 "\n",
2727 "Index: A/mu\n",
2728 "===================================================================\n",
2729 "--- A/mu\t(revision 1)\n",
2730 "+++ A/mu\t(working copy)\n",
2731 "@@ -1 +1,2 @@\n",
2732 " This is the file 'mu'.\n",
2733 "+new text\n" ]
2735 expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[:7])
2736 expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[1:22])
2737 expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[1:29])
2738 expected_infinity = svntest.verify.UnorderedOutput(diff_wc_repos[:])
2740 svntest.actions.run_and_verify_svn(None, None, [],
2741 'up', '-r1')
2743 svntest.actions.run_and_verify_svn(None, None, [],
2744 'propset',
2745 'foo1', 'baz1', '.')
2746 svntest.actions.run_and_verify_svn(None, None, [],
2747 'propset',
2748 'foo2', 'baz2', 'iota')
2749 svntest.actions.run_and_verify_svn(None, None, [],
2750 'propset',
2751 'foo3', 'baz3', 'A')
2752 svntest.actions.run_and_verify_svn(None, None, [],
2753 'propset',
2754 'foo4', 'baz4', os.path.join('A', 'B'))
2755 svntest.main.file_append(os.path.join('A', 'mu'), "new text\n")
2756 svntest.main.file_append('iota', "new text\n")
2758 # Test wc-repos diff.
2759 svntest.actions.run_and_verify_svn(None, expected_empty, [],
2760 'diff', '-rHEAD', '--depth', 'empty')
2761 svntest.actions.run_and_verify_svn(None, expected_files, [],
2762 'diff', '-rHEAD', '--depth', 'files')
2763 svntest.actions.run_and_verify_svn(None, expected_immediates, [],
2764 'diff', '-rHEAD', '--depth', 'immediates')
2765 svntest.actions.run_and_verify_svn(None, expected_infinity, [],
2766 'diff', '-rHEAD', '--depth', 'infinity')
2768 # test for issue 2920: ignore eol-style on empty lines
2769 def diff_ignore_eolstyle_empty_lines(sbox):
2770 "ignore eol styles when diffing empty lines"
2772 sbox.build()
2773 wc_dir = sbox.wc_dir
2775 file_name = "iota"
2776 file_path = os.path.join(wc_dir, file_name)
2778 svntest.main.file_write(file_path,
2779 "Aa\n"
2780 "\n"
2781 "Bb\n"
2782 "\n"
2783 "Cc\n")
2784 expected_output = svntest.wc.State(wc_dir, {
2785 'iota' : Item(verb='Sending'),
2787 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2788 None, None, wc_dir)
2790 # sleep to guarantee timestamp change
2791 time.sleep(1)
2793 # commit only eol changes
2794 svntest.main.file_write(file_path,
2795 "Aa\012"
2796 "\012"
2797 "Bb\r"
2798 "\r"
2799 "Cc\012",
2800 mode="wb")
2802 svntest.actions.run_and_verify_svn(None, [], [],
2803 'diff', '-x', '--ignore-eol-style',
2804 file_path)
2806 def diff_backward_repos_wc_copy(sbox):
2807 "backward repos->wc diff with copied file"
2809 sbox.build()
2810 wc_dir = sbox.wc_dir
2811 os.chdir(wc_dir)
2813 # copy a file
2814 mu_path = os.path.join('A', 'mu')
2815 mucp_path = os.path.join('A', 'mucopy')
2816 svntest.main.run_svn(None, 'cp', mu_path, mucp_path)
2818 # commit r2 and update back to r1
2819 svntest.main.run_svn(None,
2820 'ci', '-m', 'log msg')
2821 svntest.main.run_svn(None, 'up', '-r1')
2823 # diff r2 against working copy
2824 diff_repos_wc = [
2825 "Index: A/mucopy\n",
2826 "===================================================================\n",
2827 "--- A/mucopy\t(revision 2)\n",
2828 "+++ A/mucopy\t(working copy)\n",
2829 "@@ -1 +0,0 @@\n",
2830 "-This is the file 'mu'.\n",
2833 svntest.actions.run_and_verify_svn(None, diff_repos_wc, [],
2834 'diff', '-r' , '2')
2836 #----------------------------------------------------------------------
2838 def diff_summarize_xml(sbox):
2839 "xml diff summarize"
2841 sbox.build()
2842 wc_dir = sbox.wc_dir
2844 # A content modification.
2845 svntest.main.file_append(os.path.join(wc_dir, "A", "mu"), "New mu content")
2847 # A prop modification.
2848 svntest.main.run_svn(None,
2849 "propset", "prop", "val",
2850 os.path.join(wc_dir, 'iota'))
2852 # Both content and prop mods.
2853 tau_path = os.path.join(wc_dir, "A", "D", "G", "tau")
2854 svntest.main.file_append(tau_path, "tautau")
2855 svntest.main.run_svn(None,
2856 "propset", "prop", "val", tau_path)
2858 # A file addition.
2859 newfile_path = os.path.join(wc_dir, 'newfile')
2860 svntest.main.file_append(newfile_path, 'newfile')
2861 svntest.main.run_svn(None, 'add', newfile_path)
2863 # A file deletion.
2864 svntest.main.run_svn(None, "delete", os.path.join(wc_dir, 'A', 'B',
2865 'lambda'))
2867 # A directory addition
2868 svntest.main.run_svn(None, "mkdir", os.path.join(wc_dir, 'newdir'))
2870 expected_output = svntest.wc.State(wc_dir, {
2871 'A/mu': Item(verb='Sending'),
2872 'iota': Item(verb='Sending'),
2873 'newfile': Item(verb='Adding'),
2874 'A/D/G/tau': Item(verb='Sending'),
2875 'A/B/lambda': Item(verb='Deleting'),
2876 'newdir': Item(verb='Adding'),
2878 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
2879 expected_status.add({
2880 'newfile': Item(status=' ', wc_rev=2),
2881 'newdir': Item(status=' ', wc_rev=2),
2883 expected_status.tweak("A/mu", "iota", "A/D/G/tau", "newfile", "newdir",
2884 wc_rev=2)
2885 expected_status.remove("A/B/lambda")
2887 svntest.actions.run_and_verify_commit(wc_dir, expected_output,
2888 expected_status, None, wc_dir)
2890 # 1) Test --xml without --summarize
2891 svntest.actions.run_and_verify_svn(
2892 None, None, ".*--xml' option only valid with '--summarize' option",
2893 'diff', wc_dir, '--xml')
2895 # 2) Test --xml on invalid revision
2896 svntest.actions.run_and_verify_diff_summarize_xml(
2897 ".*No such revision 5555555",
2898 None, wc_dir, None, None, None, '-r0:5555555', wc_dir)
2900 # 3) Test working copy summarize
2901 svntest.actions.run_and_verify_diff_summarize_xml(
2902 ".*Summarizing diff can only compare repository to repository",
2903 None, wc_dir, None, None, wc_dir)
2905 # 4) Test --summarize --xml on -c2
2906 paths = ['iota',]
2907 items = ['none',]
2908 kinds = ['file',]
2909 props = ['modified',]
2911 svntest.actions.run_and_verify_diff_summarize_xml(
2912 [], wc_dir, paths, items, props, kinds, '-c2',
2913 os.path.join(wc_dir, 'iota'))
2915 # 5) Test --summarize --xml on -r1:2
2916 paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
2917 'newdir',]
2918 items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
2919 kinds = ['file','file','file','file','file', 'dir',]
2920 props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
2922 svntest.actions.run_and_verify_diff_summarize_xml(
2923 [], wc_dir, paths, items, props, kinds, '-r1:2', wc_dir)
2925 # 6) Same as test #5 but ran against a URL instead of a WC path
2926 paths = ['A/mu', 'iota', 'A/D/G/tau', 'newfile', 'A/B/lambda',
2927 'newdir',]
2928 items = ['modified', 'none', 'modified', 'added', 'deleted', 'added',]
2929 kinds = ['file','file','file','file','file', 'dir',]
2930 props = ['none', 'modified', 'modified', 'none', 'none', 'none',]
2932 svntest.actions.run_and_verify_diff_summarize_xml(
2933 [], sbox.repo_url, paths, items, props, kinds, '-r1:2', sbox.repo_url)
2935 def diff_file_depth_empty(sbox):
2936 "svn diff --depth=empty FILE_WITH_LOCAL_MODS"
2937 # The bug was that no diff output would be generated. Check that some is.
2938 sbox.build()
2939 iota_path = os.path.join(sbox.wc_dir, 'iota')
2940 svntest.main.file_append(iota_path, "new text in iota")
2941 out, err = svntest.main.run_svn(None, 'diff', '--depth', 'empty', iota_path)
2942 if err:
2943 raise svntest.Failure
2944 if len(out) < 4:
2945 raise svntest.Failure
2947 ########################################################################
2948 #Run the tests
2951 # list all tests here, starting with None:
2952 test_list = [ None,
2953 diff_update_a_file,
2954 diff_add_a_file,
2955 diff_add_a_file_in_a_subdir,
2956 diff_replace_a_file,
2957 diff_multiple_reverse,
2958 diff_non_recursive,
2959 diff_repo_subset,
2960 diff_non_version_controlled_file,
2961 diff_pure_repository_update_a_file,
2962 diff_only_property_change,
2963 dont_diff_binary_file,
2964 diff_nonextant_urls,
2965 diff_head_of_moved_file,
2966 diff_base_to_repos,
2967 diff_deleted_in_head,
2968 diff_targets,
2969 diff_branches,
2970 diff_repos_and_wc,
2971 diff_file_urls,
2972 diff_prop_change_local_edit,
2973 check_for_omitted_prefix_in_path_component,
2974 diff_renamed_file,
2975 diff_within_renamed_dir,
2976 diff_prop_on_named_dir,
2977 diff_keywords,
2978 diff_force,
2979 diff_schedule_delete,
2980 XFail(diff_renamed_dir),
2981 diff_property_changes_to_base,
2982 diff_mime_type_changes,
2983 diff_prop_change_local_propmod,
2984 diff_repos_wc_add_with_props,
2985 diff_nonrecursive_checkout_deleted_dir,
2986 diff_repos_working_added_dir,
2987 diff_base_repos_moved,
2988 diff_added_subtree,
2989 basic_diff_summarize,
2990 diff_weird_author,
2991 diff_ignore_whitespace,
2992 diff_ignore_eolstyle,
2993 diff_in_renamed_folder,
2994 diff_with_depth,
2995 diff_ignore_eolstyle_empty_lines,
2996 diff_backward_repos_wc_copy,
2997 diff_summarize_xml,
2998 diff_file_depth_empty,
3001 if __name__ == '__main__':
3002 svntest.main.run_tests(test_list)
3003 # NOTREACHED
3006 ### End of file.