3 # svnadmin_tests.py: testing the 'svnadmin' tool.
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-2006 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 ######################################################################
26 from svntest
.verify
import SVNExpectedStdout
, SVNExpectedStderr
27 from svntest
.verify
import SVNUnexpectedStderr
30 Skip
= svntest
.testcase
.Skip
31 SkipUnless
= svntest
.testcase
.SkipUnless
32 XFail
= svntest
.testcase
.XFail
33 Item
= svntest
.wc
.StateItem
36 #----------------------------------------------------------------------
38 # How we currently test 'svnadmin' --
40 # 'svnadmin create': Create an empty repository, test that the
41 # root node has a proper created-revision,
42 # because there was once a bug where it
45 # Note also that "svnadmin create" is tested
46 # implicitly every time we run a python test
47 # script. (An empty repository is always
48 # created and then imported into; if this
49 # subcommand failed catastrophically, every
50 # test would fail and we would know instantly.)
52 # 'svnadmin createtxn'
53 # 'svnadmin rmtxn': See below.
55 # 'svnadmin lstxns': We don't care about the contents of transactions;
56 # we only care that they exist or not.
57 # Therefore, we can simply parse transaction headers.
59 # 'svnadmin dump': A couple regression tests that ensure dump doesn't
60 # error out, and one to check that the --quiet option
61 # really does what it's meant to do. The actual
62 # contents of the dump aren't verified at all.
64 # ### TODO: someday maybe we could parse the contents of trees too.
66 ######################################################################
70 def get_txns(repo_dir
):
71 "Get the txn names using 'svnadmin lstxns'."
73 exit_code
, output_lines
, error_lines
= svntest
.main
.run_svnadmin('lstxns',
75 txns
= map(output_lines
.strip
, output_lines
)
82 def load_and_verify_dumpstream(sbox
, expected_stdout
, expected_stderr
,
83 revs
, dump
, *varargs
):
84 """Load the array of lines passed in 'dump' into the
85 current tests' repository and verify the repository content
86 using the array of wc.States passed in revs. VARARGS are optional
87 arguments passed to the 'load' command"""
89 if type(dump
) is type(""):
92 exit_code
, output
, errput
= svntest
.main
.run_command_stdin(
93 svntest
.main
.svnadmin_binary
, expected_stderr
, 1, dump
,
94 'load', '--quiet', sbox
.repo_dir
, *varargs
)
97 if expected_stdout
== svntest
.verify
.AnyOutput
:
99 raise SVNExpectedStdout
101 svntest
.verify
.compare_and_display_lines(
102 "Standard output", "STDOUT:", expected_stdout
, output
)
105 if expected_stderr
== svntest
.verify
.AnyOutput
:
107 raise SVNExpectedStderr
109 svntest
.verify
.compare_and_display_lines(
110 "Standard error output", "STDERR:", expected_stderr
, errput
)
111 # The expected error occurred, so don't try to verify the result
115 # verify revs as wc states
116 for rev
in xrange(len(revs
)):
117 svntest
.actions
.run_and_verify_svn("Updating to r%s" % (rev
+1),
118 svntest
.verify
.AnyOutput
, [],
119 "update", "-r%s" % (rev
+1),
122 wc_tree
= svntest
.tree
.build_tree_from_wc(sbox
.wc_dir
)
123 rev_tree
= revs
[rev
].old_tree()
126 svntest
.tree
.compare_trees ("rev/disk", rev_tree
, wc_tree
)
127 except svntest
.tree
.SVNTreeError
:
128 svntest
.verify
.display_trees(None, 'WC TREE', wc_tree
, rev_tree
)
132 ######################################################################
136 #----------------------------------------------------------------------
138 def test_create(sbox
):
142 repo_dir
= sbox
.repo_dir
145 svntest
.main
.safe_rmtree(repo_dir
, 1)
146 svntest
.main
.safe_rmtree(wc_dir
)
148 svntest
.main
.create_repos(repo_dir
)
150 svntest
.actions
.run_and_verify_svn("Creating rev 0 checkout",
151 ["Checked out revision 0.\n"], [],
153 sbox
.repo_url
, wc_dir
)
156 svntest
.actions
.run_and_verify_svn(
161 svntest
.actions
.run_and_verify_svn(
162 "Running verbose status",
163 [" 0 0 ? %s\n" % wc_dir
], [],
164 "status", "--verbose", wc_dir
)
169 # dump stream tests need a dump file
171 def clean_dumpfile():
173 [ "SVN-fs-dump-format-version: 2\n\n",
174 "UUID: 668cc64a-31ed-0310-8ccb-b75d75bb44e3\n\n",
175 "Revision-number: 0\n",
176 "Prop-content-length: 56\n",
177 "Content-length: 56\n\n",
178 "K 8\nsvn:date\nV 27\n2005-01-08T21:48:13.838745Z\nPROPS-END\n\n\n",
179 "Revision-number: 1\n",
180 "Prop-content-length: 98\n",
181 "Content-length: 98\n\n",
182 "K 7\nsvn:log\nV 0\n\nK 10\nsvn:author\nV 4\nerik\n",
183 "K 8\nsvn:date\nV 27\n2005-01-08T21:51:16.313791Z\nPROPS-END\n\n\n",
186 "Node-action: add\n",
187 "Prop-content-length: 35\n",
188 "Text-content-length: 5\n",
189 "Text-content-md5: e1cbb0c3879af8347246f12c559a86b5\n",
190 "Content-length: 40\n\n",
191 "K 12\nsvn:keywords\nV 2\nId\nPROPS-END\ntext\n\n\n"]
193 dumpfile_revisions
= \
194 [ svntest
.wc
.State('', { 'A' : svntest
.wc
.StateItem(contents
="text\n") }) ]
196 #----------------------------------------------------------------------
197 def extra_headers(sbox
):
198 "loading of dumpstream with extra headers"
202 dumpfile
= clean_dumpfile()
205 [ "X-Comment-Header: Ignored header normally not in dump stream\n" ]
207 load_and_verify_dumpstream(sbox
,[],[], dumpfile_revisions
, dumpfile
,
210 #----------------------------------------------------------------------
211 # Ensure loading continues after skipping a bit of unknown extra content.
212 def extra_blockcontent(sbox
):
213 "load success on oversized Content-length"
217 dumpfile
= clean_dumpfile()
219 # Replace "Content-length" line with two lines
221 [ "Extra-content-length: 10\n",
222 "Content-length: 108\n\n" ]
223 # Insert the extra content after "PROPS-END\n"
224 dumpfile
[11] = dumpfile
[11][:-2] + "extra text\n\n\n"
226 load_and_verify_dumpstream(sbox
,[],[], dumpfile_revisions
, dumpfile
,
229 #----------------------------------------------------------------------
230 def inconsistent_headers(sbox
):
231 "load failure on undersized Content-length"
235 dumpfile
= clean_dumpfile()
237 dumpfile
[-2] = "Content-length: 30\n\n"
239 load_and_verify_dumpstream(sbox
, [], svntest
.verify
.AnyOutput
,
240 dumpfile_revisions
, dumpfile
)
242 #----------------------------------------------------------------------
243 # Test for issue #2729: Datestamp-less revisions in dump streams do
244 # not remain so after load
245 def empty_date(sbox
):
246 "preserve date-less revisions in load (issue #2729)"
250 dumpfile
= clean_dumpfile()
252 # Replace portions of the revision data to drop the svn:date revprop.
254 [ "Prop-content-length: 52\n",
255 "Content-length: 52\n\n",
256 "K 7\nsvn:log\nV 0\n\nK 10\nsvn:author\nV 4\nerik\nPROPS-END\n\n\n"
259 load_and_verify_dumpstream(sbox
,[],[], dumpfile_revisions
, dumpfile
,
262 # Verify that the revision still lacks the svn:date property.
263 svntest
.actions
.run_and_verify_svn(None, [], [], "propget",
264 "--revprop", "-r1", "svn:date",
267 #----------------------------------------------------------------------
269 def dump_copied_dir(sbox
):
270 "'svnadmin dump' on copied directory"
274 repo_dir
= sbox
.repo_dir
276 old_C_path
= os
.path
.join(wc_dir
, 'A', 'C')
277 new_C_path
= os
.path
.join(wc_dir
, 'A', 'B', 'C')
278 svntest
.main
.run_svn(None, 'cp', old_C_path
, new_C_path
)
279 svntest
.main
.run_svn(None, 'ci', wc_dir
, '--quiet',
282 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", repo_dir
)
283 if svntest
.verify
.compare_and_display_lines(
284 "Output of 'svnadmin dump' is unexpected.",
285 'STDERR', ["* Dumped revision 0.\n",
286 "* Dumped revision 1.\n",
287 "* Dumped revision 2.\n"], errput
):
288 raise svntest
.Failure
290 #----------------------------------------------------------------------
292 def dump_move_dir_modify_child(sbox
):
293 "'svnadmin dump' on modified child of copied dir"
297 repo_dir
= sbox
.repo_dir
299 B_path
= os
.path
.join(wc_dir
, 'A', 'B')
300 Q_path
= os
.path
.join(wc_dir
, 'A', 'Q')
301 svntest
.main
.run_svn(None, 'cp', B_path
, Q_path
)
302 svntest
.main
.file_append(os
.path
.join(Q_path
, 'lambda'), 'hello')
303 svntest
.main
.run_svn(None, 'ci', wc_dir
, '--quiet',
305 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", repo_dir
)
306 svntest
.verify
.compare_and_display_lines(
307 "Output of 'svnadmin dump' is unexpected.",
308 'STDERR', ["* Dumped revision 0.\n",
309 "* Dumped revision 1.\n",
310 "* Dumped revision 2.\n"], errput
)
312 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", "-r",
314 svntest
.verify
.compare_and_display_lines(
315 "Output of 'svnadmin dump' is unexpected.",
316 'STDERR', ["* Dumped revision 0.\n",
317 "* Dumped revision 1.\n",
318 "* Dumped revision 2.\n"], errput
)
320 #----------------------------------------------------------------------
322 def dump_quiet(sbox
):
323 "'svnadmin dump --quiet'"
325 sbox
.build(create_wc
= False)
327 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", sbox
.repo_dir
,
329 svntest
.verify
.compare_and_display_lines(
330 "Output of 'svnadmin dump --quiet' is unexpected.",
331 'STDERR', [], errput
)
333 #----------------------------------------------------------------------
335 def hotcopy_dot(sbox
):
336 "'svnadmin hotcopy PATH .'"
339 backup_dir
, backup_url
= sbox
.add_repo_path('backup')
344 exit_code
, output
, errput
= svntest
.main
.run_svnadmin(
345 "hotcopy", os
.path
.join(cwd
, sbox
.repo_dir
), '.')
348 raise svntest
.Failure
352 exit_code
, origout
, origerr
= svntest
.main
.run_svnadmin("dump",
355 exit_code
, backout
, backerr
= svntest
.main
.run_svnadmin("dump",
358 if origerr
or backerr
or origout
!= backout
:
359 raise svntest
.Failure
361 #----------------------------------------------------------------------
363 def hotcopy_format(sbox
):
364 "'svnadmin hotcopy' checking db/format file"
367 backup_dir
, backup_url
= sbox
.add_repo_path('backup')
368 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("hotcopy",
372 print "Error: hotcopy failed"
373 raise svntest
.Failure
375 # verify that the db/format files are the same
376 fp
= open(os
.path
.join(sbox
.repo_dir
, "db", "format"))
377 contents1
= fp
.read()
380 fp2
= open(os
.path
.join(backup_dir
, "db", "format"))
381 contents2
= fp2
.read()
384 if contents1
!= contents2
:
385 print "Error: db/format file contents do not match after hotcopy"
386 raise svntest
.Failure
388 #----------------------------------------------------------------------
390 def setrevprop(sbox
):
391 "'setlog' and 'setrevprop', bypassing hooks'"
394 # Try a simple log property modification.
395 iota_path
= os
.path
.join(sbox
.wc_dir
, "iota")
396 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("setlog",
402 print "Error: 'setlog' failed"
403 raise svntest
.Failure
405 # Verify that the revprop value matches what we set when retrieved
406 # through the client.
407 svntest
.actions
.run_and_verify_svn(None,
408 [ "This is the file 'iota'.\n", "\n" ],
409 [], "propget", "--revprop", "-r0",
410 "svn:log", sbox
.wc_dir
)
412 # Try an author property modification.
413 foo_path
= os
.path
.join(sbox
.wc_dir
, "foo")
414 svntest
.main
.file_write(foo_path
, "foo")
416 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("setrevprop",
421 print "Error: 'setrevprop' failed"
422 raise svntest
.Failure
424 # Verify that the revprop value matches what we set when retrieved
425 # through the client.
426 svntest
.actions
.run_and_verify_svn(None, [ "foo\n" ], [], "propget",
427 "--revprop", "-r0", "svn:author",
430 def verify_windows_paths_in_repos(sbox
):
431 "verify a repository containing paths like 'c:hi'"
433 # setup a repo with a directory 'c:hi'
434 sbox
.build(create_wc
= False)
435 repo_url
= sbox
.repo_url
436 chi_url
= sbox
.repo_url
+ '/c:hi'
438 svntest
.actions
.run_and_verify_svn(None, None, [],
439 'mkdir', '-m', 'log_msg',
442 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("verify",
444 svntest
.verify
.compare_and_display_lines(
445 "Error while running 'svnadmin verify'.",
446 'STDERR', ["* Verified revision 0.\n",
447 "* Verified revision 1.\n",
448 "* Verified revision 2.\n"], errput
)
450 #----------------------------------------------------------------------
452 # Returns the filename of the rev or revprop file (according to KIND)
453 # numbered REV in REPO_DIR, which must be in the first shard if we're
454 # using a sharded repository.
455 def fsfs_file(repo_dir
, kind
, rev
):
456 if svntest
.main
.server_minor_version
>= 5:
457 return os
.path
.join(repo_dir
, 'db', kind
, '0', rev
)
459 return os
.path
.join(repo_dir
, 'db', kind
, rev
)
462 def verify_incremental_fsfs(sbox
):
463 """svnadmin verify detects corruption dump can't"""
465 # setup a repo with a directory 'c:hi'
466 sbox
.build(create_wc
= False)
467 repo_url
= sbox
.repo_url
468 E_url
= sbox
.repo_url
+ '/A/B/E'
470 # Create A/B/E/bravo in r2.
471 svntest
.actions
.run_and_verify_svn(None, None, [],
472 'mkdir', '-m', 'log_msg',
474 # Corrupt r2's reference to A/C by replacing "dir 7-1.0.r1/1568" with
475 # "dir 7-1.0.r1/1569" (increment offset) and updating the checksum for
476 # this directory listing to "c9b5a2d26473a4e28088673dda9df804" so that
477 # the listing itself is valid.
478 r2
= fsfs_file(sbox
.repo_dir
, 'revs', '2')
480 fp
.write("""id: 0-2.0.r2/0
505 text: 2 69 99 99 f63001f7fddd1842d8891474d0982111
528 text: 2 316 95 95 bccb66379b4f825dac12b50d80211bae
555 text: 2 558 121 121 c9b5a2d26473a4e28088673dda9df804
574 text: 2 826 65 65 e44e4151d0d124533338619f082c8c9a
578 _0.0.t1-1 add false false /A/B/E/bravo
585 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("verify", "-r2",
587 svntest
.verify
.verify_outputs(
588 message
=None, actual_stdout
=output
, actual_stderr
=errput
,
589 expected_stdout
=None,
590 expected_stderr
=".*Missing id field in node-rev")
592 #----------------------------------------------------------------------
594 def recover_fsfs(sbox
):
595 "recover a repository (FSFS only)"
597 current_path
= os
.path
.join(sbox
.repo_dir
, 'db', 'current')
599 # Commit up to r3, so we can test various recovery scenarios.
600 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newer line\n')
601 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
603 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newest line\n')
604 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
606 # Remember the contents of the db/current file.
607 expected_current_contents
= svntest
.main
.file_read(current_path
)
609 # Move aside the current file for r3.
610 os
.rename(os
.path
.join(sbox
.repo_dir
, 'db','current'),
611 os
.path
.join(sbox
.repo_dir
, 'db','was_current'));
613 # Run 'svnadmin recover' and check that the current file is recreated.
614 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
617 raise SVNUnexpectedStderr(errput
)
619 actual_current_contents
= svntest
.main
.file_read(current_path
)
620 svntest
.verify
.compare_and_display_lines(
621 "Contents of db/current is unexpected.",
622 'db/current', expected_current_contents
, actual_current_contents
)
624 # Now try writing db/current to be one rev lower than it should be.
625 svntest
.main
.file_write(current_path
, '2\n')
627 # Run 'svnadmin recover' and check that the current file is fixed.
628 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
631 raise SVNUnexpectedStderr(errput
)
633 actual_current_contents
= svntest
.main
.file_read(current_path
)
634 svntest
.verify
.compare_and_display_lines(
635 "Contents of db/current is unexpected.",
636 'db/current', expected_current_contents
, actual_current_contents
)
638 # Now try writing db/current to be *two* revs lower than it should be.
639 svntest
.main
.file_write(current_path
, '1\n')
641 # Run 'svnadmin recover' and check that the current file is fixed.
642 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
645 raise SVNUnexpectedStderr(errput
)
647 actual_current_contents
= svntest
.main
.file_read(current_path
)
648 svntest
.verify
.compare_and_display_lines(
649 "Contents of db/current is unexpected.",
650 'db/current', expected_current_contents
, actual_current_contents
)
652 # Now try writing db/current to be fish revs lower than it should be.
654 # Note: I'm not actually sure it's wise to recover from this, but
655 # detecting it would require rewriting fs_fs.c:get_youngest() to
656 # check the actual contents of its buffer, since atol() will happily
657 # convert "fish" to 0.
658 svntest
.main
.file_write(current_path
, 'fish\n')
660 # Run 'svnadmin recover' and check that the current file is fixed.
661 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
664 raise SVNUnexpectedStderr(errput
)
666 actual_current_contents
= svntest
.main
.file_read(current_path
)
667 svntest
.verify
.compare_and_display_lines(
668 "Contents of db/current is unexpected.",
669 'db/current', expected_current_contents
, actual_current_contents
)
671 #----------------------------------------------------------------------
673 def load_with_parent_dir(sbox
):
674 "'svnadmin load --parent-dir' reparents mergeinfo"
676 ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2983. ##
679 dumpfile_location
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]),
680 'svnadmin_tests_data',
681 'mergeinfo_included.dump')
682 dumpfile
= svntest
.main
.file_read(dumpfile_location
)
684 # Create 'sample' dir in sbox.repo_url
685 svntest
.actions
.run_and_verify_svn(None,
686 ['\n', 'Committed revision 1.\n'],
687 [], "mkdir", sbox
.repo_url
+ "/sample",
688 "-m", "Create sample dir")
690 # Load the dump stream
691 load_and_verify_dumpstream(sbox
,[],[], None, dumpfile
, '--parent-dir',
694 # Verify the svn:mergeinfo properties for '--parent-dir'
695 svntest
.actions
.run_and_verify_svn(None,
697 "/sample/branch - /sample/trunk:5-7\n"],
698 [], 'propget', 'svn:mergeinfo', '-R',
699 sbox
.repo_url
+ '/sample/branch')
700 svntest
.actions
.run_and_verify_svn(None,
702 "/sample/branch1 - " +
703 "/sample/branch:6-9\n"],
704 [], 'propget', 'svn:mergeinfo', '-R',
705 sbox
.repo_url
+ '/sample/branch1')
707 #----------------------------------------------------------------------
710 "test 'svnadmin setuuid'"
712 sbox
.build(create_wc
=False)
714 # Squirrel away the original repository UUID.
715 exit_code
, output
, errput
= svntest
.main
.run_svnlook('uuid', sbox
.repo_dir
)
717 raise SVNUnexpectedStderr(errput
)
718 orig_uuid
= output
[0].rstrip()
720 # Try setting a new, bogus UUID.
721 svntest
.actions
.run_and_verify_svnadmin(None, None, '^.*Malformed UUID.*$',
722 'setuuid', sbox
.repo_dir
, 'abcdef')
724 # Try generating a brand new UUID.
725 svntest
.actions
.run_and_verify_svnadmin(None, [], None,
726 'setuuid', sbox
.repo_dir
)
727 exit_code
, output
, errput
= svntest
.main
.run_svnlook('uuid', sbox
.repo_dir
)
729 raise SVNUnexpectedStderr(errput
)
730 new_uuid
= output
[0].rstrip()
731 if new_uuid
== orig_uuid
:
732 print "Error: new UUID matches the original one"
733 raise svntest
.Failure
735 # Now, try setting the UUID back to the original value.
736 svntest
.actions
.run_and_verify_svnadmin(None, [], None,
737 'setuuid', sbox
.repo_dir
, orig_uuid
)
738 exit_code
, output
, errput
= svntest
.main
.run_svnlook('uuid', sbox
.repo_dir
)
740 raise SVNUnexpectedStderr(errput
)
741 new_uuid
= output
[0].rstrip()
742 if new_uuid
!= orig_uuid
:
743 print "Error: new UUID doesn't match the original one"
744 raise svntest
.Failure
746 #----------------------------------------------------------------------
748 def reflect_dropped_renumbered_revs(sbox
):
749 "reflect dropped renumbered revs in svn:mergeinfo"
751 ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3020. ##
755 dumpfile_location
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]),
756 'svndumpfilter_tests_data',
758 dumpfile
= svntest
.main
.file_read(dumpfile_location
)
760 # Create 'toplevel' dir in sbox.repo_url
761 svntest
.actions
.run_and_verify_svn(None, ['\n', 'Committed revision 1.\n'],
762 [], "mkdir", sbox
.repo_url
+ "/toplevel",
763 "-m", "Create toplevel dir")
765 # Load the dump stream in sbox.repo_url
766 load_and_verify_dumpstream(sbox
,[],[], None, dumpfile
)
768 # Load the dump stream in toplevel dir
769 load_and_verify_dumpstream(sbox
,[],[], None, dumpfile
, '--parent-dir',
772 # Verify the svn:mergeinfo properties
773 svntest
.actions
.run_and_verify_svn(None, ["/trunk:1-4\n"],
774 [], 'propget', 'svn:mergeinfo',
775 sbox
.repo_url
+ '/branch2')
776 svntest
.actions
.run_and_verify_svn(None, ["/branch1:5-9\n"],
777 [], 'propget', 'svn:mergeinfo',
778 sbox
.repo_url
+ '/trunk')
779 svntest
.actions
.run_and_verify_svn(None, ["/toplevel/trunk:1-13\n"],
780 [], 'propget', 'svn:mergeinfo',
781 sbox
.repo_url
+ '/toplevel/branch2')
782 svntest
.actions
.run_and_verify_svn(None, ["/toplevel/branch1:14-18\n"],
783 [], 'propget', 'svn:mergeinfo',
784 sbox
.repo_url
+ '/toplevel/trunk')
785 svntest
.actions
.run_and_verify_svn(None, ["/toplevel/trunk:1-12\n"],
786 [], 'propget', 'svn:mergeinfo',
787 sbox
.repo_url
+ '/toplevel/branch1')
788 svntest
.actions
.run_and_verify_svn(None, ["/trunk:1-3\n"],
789 [], 'propget', 'svn:mergeinfo',
790 sbox
.repo_url
+ '/branch1')
792 #----------------------------------------------------------------------
794 def fsfs_recover_handle_missing_revs_or_revprops_file(sbox
):
795 """fsfs recovery checks missing revs / revprops files"""
796 # Set up a repository containing the greek tree.
799 # Commit up to r3, so we can test various recovery scenarios.
800 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newer line\n')
801 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
803 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newest line\n')
804 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
806 rev_3
= fsfs_file(sbox
.repo_dir
, 'revs', '3')
807 rev_was_3
= fsfs_file(sbox
.repo_dir
, 'revs', 'was_3')
809 # Move aside the revs file for r3.
810 os
.rename(rev_3
, rev_was_3
)
812 # Verify 'svnadmin recover' fails when youngest has a revprops
813 # file but no revs file.
814 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
817 if svntest
.verify
.verify_outputs(
818 "Output of 'svnadmin recover' is unexpected.", None, errput
, None,
819 ".*Expected current rev to be <= 2 but found 3"):
820 raise svntest
.Failure
822 # Restore the r3 revs file, thus repairing the repository.
823 os
.rename(rev_was_3
, rev_3
)
825 revprop_3
= fsfs_file(sbox
.repo_dir
, 'revprops', '3')
826 revprop_was_3
= fsfs_file(sbox
.repo_dir
, 'revprops', 'was_3')
828 # Move aside the revprops file for r3.
829 os
.rename(revprop_3
, revprop_was_3
)
831 # Verify 'svnadmin recover' fails when youngest has a revs file
832 # but no revprops file (issue #2992).
833 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
836 if svntest
.verify
.verify_outputs(
837 "Output of 'svnadmin recover' is unexpected.", None, errput
, None,
838 ".*Revision 3 has a revs file but no revprops file"):
839 raise svntest
.Failure
841 # Restore the r3 revprops file, thus repairing the repository.
842 os
.rename(revprop_was_3
, revprop_3
)
844 # Change revprops file to a directory for revision 3
845 os
.rename(revprop_3
, revprop_was_3
)
848 # Verify 'svnadmin recover' fails when youngest has a revs file
849 # but revprops file is not a file (another aspect of issue #2992).
850 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
853 if svntest
.verify
.verify_outputs(
854 "Output of 'svnadmin recover' is unexpected.", None, errput
, None,
855 ".*Revision 3 has a non-file where its revprops file should be.*"):
856 raise svntest
.Failure
858 ########################################################################
862 # list all tests here, starting with None:
866 inconsistent_headers
,
869 dump_move_dir_modify_child
,
874 verify_windows_paths_in_repos
,
875 SkipUnless(verify_incremental_fsfs
, svntest
.main
.is_fs_type_fsfs
),
876 SkipUnless(recover_fsfs
, svntest
.main
.is_fs_type_fsfs
),
877 load_with_parent_dir
,
879 reflect_dropped_renumbered_revs
,
880 SkipUnless(fsfs_recover_handle_missing_revs_or_revprops_file
,
881 svntest
.main
.is_fs_type_fsfs
),
884 if __name__
== '__main__':
885 svntest
.main
.run_tests(test_list
)