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
)
209 #----------------------------------------------------------------------
210 # Ensure loading continues after skipping a bit of unknown extra content.
211 def extra_blockcontent(sbox
):
212 "load success on oversized Content-length"
216 dumpfile
= clean_dumpfile()
218 # Replace "Content-length" line with two lines
220 [ "Extra-content-length: 10\n",
221 "Content-length: 108\n\n" ]
222 # Insert the extra content after "PROPS-END\n"
223 dumpfile
[11] = dumpfile
[11][:-2] + "extra text\n\n\n"
225 load_and_verify_dumpstream(sbox
,[],[], dumpfile_revisions
, dumpfile
)
227 #----------------------------------------------------------------------
228 def inconsistent_headers(sbox
):
229 "load failure on undersized Content-length"
233 dumpfile
= clean_dumpfile()
235 dumpfile
[-2] = "Content-length: 30\n\n"
237 load_and_verify_dumpstream(sbox
, [], svntest
.verify
.AnyOutput
,
238 dumpfile_revisions
, dumpfile
)
240 #----------------------------------------------------------------------
241 # Test for issue #2729: Datestamp-less revisions in dump streams do
242 # not remain so after load
243 def empty_date(sbox
):
244 "preserve date-less revisions in load (issue #2729)"
248 dumpfile
= clean_dumpfile()
250 # Replace portions of the revision data to drop the svn:date revprop.
252 [ "Prop-content-length: 52\n",
253 "Content-length: 52\n\n",
254 "K 7\nsvn:log\nV 0\n\nK 10\nsvn:author\nV 4\nerik\nPROPS-END\n\n\n"
257 load_and_verify_dumpstream(sbox
,[],[], dumpfile_revisions
, dumpfile
)
259 # Verify that the revision still lacks the svn:date property.
260 svntest
.actions
.run_and_verify_svn(None, [], [], "propget",
261 "--revprop", "-r1", "svn:date",
264 #----------------------------------------------------------------------
266 def dump_copied_dir(sbox
):
267 "'svnadmin dump' on copied directory"
271 repo_dir
= sbox
.repo_dir
273 old_C_path
= os
.path
.join(wc_dir
, 'A', 'C')
274 new_C_path
= os
.path
.join(wc_dir
, 'A', 'B', 'C')
275 svntest
.main
.run_svn(None, 'cp', old_C_path
, new_C_path
)
276 svntest
.main
.run_svn(None, 'ci', wc_dir
, '--quiet',
279 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", repo_dir
)
280 if svntest
.verify
.compare_and_display_lines(
281 "Output of 'svnadmin dump' is unexpected.",
282 'STDERR', ["* Dumped revision 0.\n",
283 "* Dumped revision 1.\n",
284 "* Dumped revision 2.\n"], errput
):
285 raise svntest
.Failure
287 #----------------------------------------------------------------------
289 def dump_move_dir_modify_child(sbox
):
290 "'svnadmin dump' on modified child of copied dir"
294 repo_dir
= sbox
.repo_dir
296 B_path
= os
.path
.join(wc_dir
, 'A', 'B')
297 Q_path
= os
.path
.join(wc_dir
, 'A', 'Q')
298 svntest
.main
.run_svn(None, 'cp', B_path
, Q_path
)
299 svntest
.main
.file_append(os
.path
.join(Q_path
, 'lambda'), 'hello')
300 svntest
.main
.run_svn(None, 'ci', wc_dir
, '--quiet',
302 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", repo_dir
)
303 svntest
.verify
.compare_and_display_lines(
304 "Output of 'svnadmin dump' is unexpected.",
305 'STDERR', ["* Dumped revision 0.\n",
306 "* Dumped revision 1.\n",
307 "* Dumped revision 2.\n"], errput
)
309 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", "-r",
311 svntest
.verify
.compare_and_display_lines(
312 "Output of 'svnadmin dump' is unexpected.",
313 'STDERR', ["* Dumped revision 0.\n",
314 "* Dumped revision 1.\n",
315 "* Dumped revision 2.\n"], errput
)
317 #----------------------------------------------------------------------
319 def dump_quiet(sbox
):
320 "'svnadmin dump --quiet'"
322 sbox
.build(create_wc
= False)
324 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("dump", sbox
.repo_dir
,
326 svntest
.verify
.compare_and_display_lines(
327 "Output of 'svnadmin dump --quiet' is unexpected.",
328 'STDERR', [], errput
)
330 #----------------------------------------------------------------------
332 def hotcopy_dot(sbox
):
333 "'svnadmin hotcopy PATH .'"
336 backup_dir
, backup_url
= sbox
.add_repo_path('backup')
341 exit_code
, output
, errput
= svntest
.main
.run_svnadmin(
342 "hotcopy", os
.path
.join(cwd
, sbox
.repo_dir
), '.')
345 raise svntest
.Failure
349 exit_code
, origout
, origerr
= svntest
.main
.run_svnadmin("dump",
352 exit_code
, backout
, backerr
= svntest
.main
.run_svnadmin("dump",
355 if origerr
or backerr
or origout
!= backout
:
356 raise svntest
.Failure
358 #----------------------------------------------------------------------
360 def hotcopy_format(sbox
):
361 "'svnadmin hotcopy' checking db/format file"
364 backup_dir
, backup_url
= sbox
.add_repo_path('backup')
365 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("hotcopy",
369 print "Error: hotcopy failed"
370 raise svntest
.Failure
372 # verify that the db/format files are the same
373 fp
= open(os
.path
.join(sbox
.repo_dir
, "db", "format"))
374 contents1
= fp
.read()
377 fp2
= open(os
.path
.join(backup_dir
, "db", "format"))
378 contents2
= fp2
.read()
381 if contents1
!= contents2
:
382 print "Error: db/format file contents do not match after hotcopy"
383 raise svntest
.Failure
385 #----------------------------------------------------------------------
387 def setrevprop(sbox
):
388 "'setlog' and 'setrevprop', bypassing hooks'"
391 # Try a simple log property modification.
392 iota_path
= os
.path
.join(sbox
.wc_dir
, "iota")
393 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("setlog",
399 print "Error: 'setlog' failed"
400 raise svntest
.Failure
402 # Verify that the revprop value matches what we set when retrieved
403 # through the client.
404 svntest
.actions
.run_and_verify_svn(None,
405 [ "This is the file 'iota'.\n", "\n" ],
406 [], "propget", "--revprop", "-r0",
407 "svn:log", sbox
.wc_dir
)
409 # Try an author property modification.
410 foo_path
= os
.path
.join(sbox
.wc_dir
, "foo")
411 svntest
.main
.file_write(foo_path
, "foo")
413 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("setrevprop",
418 print "Error: 'setrevprop' failed"
419 raise svntest
.Failure
421 # Verify that the revprop value matches what we set when retrieved
422 # through the client.
423 svntest
.actions
.run_and_verify_svn(None, [ "foo\n" ], [], "propget",
424 "--revprop", "-r0", "svn:author",
427 def verify_windows_paths_in_repos(sbox
):
428 "verify a repository containing paths like 'c:hi'"
430 # setup a repo with a directory 'c:hi'
431 sbox
.build(create_wc
= False)
432 repo_url
= sbox
.repo_url
433 chi_url
= sbox
.repo_url
+ '/c:hi'
435 svntest
.actions
.run_and_verify_svn(None, None, [],
436 'mkdir', '-m', 'log_msg',
439 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("verify",
441 svntest
.verify
.compare_and_display_lines(
442 "Error while running 'svnadmin verify'.",
443 'STDERR', ["* Verified revision 0.\n",
444 "* Verified revision 1.\n",
445 "* Verified revision 2.\n"], errput
)
447 #----------------------------------------------------------------------
449 # Returns the filename of the rev or revprop file (according to KIND)
450 # numbered REV in REPO_DIR, which must be in the first shard if we're
451 # using a sharded repository.
452 def fsfs_file(repo_dir
, kind
, rev
):
453 if svntest
.main
.server_minor_version
>= 5:
454 return os
.path
.join(repo_dir
, 'db', kind
, '0', rev
)
456 return os
.path
.join(repo_dir
, 'db', kind
, rev
)
459 def verify_incremental_fsfs(sbox
):
460 """svnadmin verify detects corruption dump can't"""
462 # setup a repo with a directory 'c:hi'
463 sbox
.build(create_wc
= False)
464 repo_url
= sbox
.repo_url
465 E_url
= sbox
.repo_url
+ '/A/B/E'
467 # Create A/B/E/bravo in r2.
468 svntest
.actions
.run_and_verify_svn(None, None, [],
469 'mkdir', '-m', 'log_msg',
471 # Corrupt r2's reference to A/C by replacing "dir 7-1.0.r1/1568" with
472 # "dir 7-1.0.r1/1569" (increment offset) and updating the checksum for
473 # this directory listing to "c9b5a2d26473a4e28088673dda9df804" so that
474 # the listing itself is valid.
475 r2
= fsfs_file(sbox
.repo_dir
, 'revs', '2')
477 fp
.write("""id: 0-2.0.r2/0
502 text: 2 69 99 99 f63001f7fddd1842d8891474d0982111
525 text: 2 316 95 95 bccb66379b4f825dac12b50d80211bae
552 text: 2 558 121 121 c9b5a2d26473a4e28088673dda9df804
571 text: 2 826 65 65 e44e4151d0d124533338619f082c8c9a
575 _0.0.t1-1 add false false /A/B/E/bravo
582 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("verify", "-r2",
584 svntest
.verify
.verify_outputs(
585 message
=None, actual_stdout
=output
, actual_stderr
=errput
,
586 expected_stdout
=None,
587 expected_stderr
=".*Missing id field in node-rev")
589 #----------------------------------------------------------------------
591 def recover_fsfs(sbox
):
592 "recover a repository (FSFS only)"
594 current_path
= os
.path
.join(sbox
.repo_dir
, 'db', 'current')
596 # Commit up to r3, so we can test various recovery scenarios.
597 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newer line\n')
598 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
600 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newest line\n')
601 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
603 # Remember the contents of the db/current file.
604 expected_current_contents
= svntest
.main
.file_read(current_path
)
606 # Move aside the current file for r3.
607 os
.rename(os
.path
.join(sbox
.repo_dir
, 'db','current'),
608 os
.path
.join(sbox
.repo_dir
, 'db','was_current'));
610 # Run 'svnadmin recover' and check that the current file is recreated.
611 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
614 raise SVNUnexpectedStderr(errput
)
616 actual_current_contents
= svntest
.main
.file_read(current_path
)
617 svntest
.verify
.compare_and_display_lines(
618 "Contents of db/current is unexpected.",
619 'db/current', expected_current_contents
, actual_current_contents
)
621 # Now try writing db/current to be one rev lower than it should be.
622 svntest
.main
.file_write(current_path
, '2\n')
624 # Run 'svnadmin recover' and check that the current file is fixed.
625 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
628 raise SVNUnexpectedStderr(errput
)
630 actual_current_contents
= svntest
.main
.file_read(current_path
)
631 svntest
.verify
.compare_and_display_lines(
632 "Contents of db/current is unexpected.",
633 'db/current', expected_current_contents
, actual_current_contents
)
635 # Now try writing db/current to be *two* revs lower than it should be.
636 svntest
.main
.file_write(current_path
, '1\n')
638 # Run 'svnadmin recover' and check that the current file is fixed.
639 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
642 raise SVNUnexpectedStderr(errput
)
644 actual_current_contents
= svntest
.main
.file_read(current_path
)
645 svntest
.verify
.compare_and_display_lines(
646 "Contents of db/current is unexpected.",
647 'db/current', expected_current_contents
, actual_current_contents
)
649 # Now try writing db/current to be fish revs lower than it should be.
651 # Note: I'm not actually sure it's wise to recover from this, but
652 # detecting it would require rewriting fs_fs.c:get_youngest() to
653 # check the actual contents of its buffer, since atol() will happily
654 # convert "fish" to 0.
655 svntest
.main
.file_write(current_path
, 'fish\n')
657 # Run 'svnadmin recover' and check that the current file is fixed.
658 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
661 raise SVNUnexpectedStderr(errput
)
663 actual_current_contents
= svntest
.main
.file_read(current_path
)
664 svntest
.verify
.compare_and_display_lines(
665 "Contents of db/current is unexpected.",
666 'db/current', expected_current_contents
, actual_current_contents
)
668 #----------------------------------------------------------------------
670 def load_with_parent_dir(sbox
):
671 "'svnadmin load --parent-dir' reparents mergeinfo"
673 ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2983. ##
676 dumpfile_location
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]),
677 'svnadmin_tests_data',
678 'mergeinfo_included.dump')
679 dumpfile
= svntest
.main
.file_read(dumpfile_location
)
681 # Create 'sample' dir in sbox.repo_url
682 svntest
.actions
.run_and_verify_svn(None,
683 ['\n', 'Committed revision 1.\n'],
684 [], "mkdir", sbox
.repo_url
+ "/sample",
685 "-m", "Create sample dir")
687 # Load the dump stream
688 load_and_verify_dumpstream(sbox
,[],[], None, dumpfile
, '--parent-dir',
691 # Verify the svn:mergeinfo properties for '--parent-dir'
692 svntest
.actions
.run_and_verify_svn(None,
694 "/sample/branch - /sample/trunk:5-7\n"],
695 [], 'propget', 'svn:mergeinfo', '-R',
696 sbox
.repo_url
+ '/sample/branch')
697 svntest
.actions
.run_and_verify_svn(None,
699 "/sample/branch1 - " +
700 "/sample/branch:6-9\n"],
701 [], 'propget', 'svn:mergeinfo', '-R',
702 sbox
.repo_url
+ '/sample/branch1')
704 #----------------------------------------------------------------------
707 "test 'svnadmin setuuid'"
709 sbox
.build(create_wc
=False)
711 # Squirrel away the original repository UUID.
712 exit_code
, output
, errput
= svntest
.main
.run_svnlook('uuid', sbox
.repo_dir
)
714 raise SVNUnexpectedStderr(errput
)
715 orig_uuid
= output
[0].rstrip()
717 # Try setting a new, bogus UUID.
718 svntest
.actions
.run_and_verify_svnadmin(None, None, '^.*Malformed UUID.*$',
719 'setuuid', sbox
.repo_dir
, 'abcdef')
721 # Try generating a brand new UUID.
722 svntest
.actions
.run_and_verify_svnadmin(None, [], None,
723 'setuuid', sbox
.repo_dir
)
724 exit_code
, output
, errput
= svntest
.main
.run_svnlook('uuid', sbox
.repo_dir
)
726 raise SVNUnexpectedStderr(errput
)
727 new_uuid
= output
[0].rstrip()
728 if new_uuid
== orig_uuid
:
729 print "Error: new UUID matches the original one"
730 raise svntest
.Failure
732 # Now, try setting the UUID back to the original value.
733 svntest
.actions
.run_and_verify_svnadmin(None, [], None,
734 'setuuid', sbox
.repo_dir
, orig_uuid
)
735 exit_code
, output
, errput
= svntest
.main
.run_svnlook('uuid', sbox
.repo_dir
)
737 raise SVNUnexpectedStderr(errput
)
738 new_uuid
= output
[0].rstrip()
739 if new_uuid
!= orig_uuid
:
740 print "Error: new UUID doesn't match the original one"
741 raise svntest
.Failure
743 #----------------------------------------------------------------------
745 def reflect_dropped_renumbered_revs(sbox
):
746 "reflect dropped renumbered revs in svn:mergeinfo"
748 ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3020. ##
752 dumpfile_location
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]),
753 'svndumpfilter_tests_data',
755 dumpfile
= svntest
.main
.file_read(dumpfile_location
)
757 # Create 'toplevel' dir in sbox.repo_url
758 svntest
.actions
.run_and_verify_svn(None, ['\n', 'Committed revision 1.\n'],
759 [], "mkdir", sbox
.repo_url
+ "/toplevel",
760 "-m", "Create toplevel dir")
762 # Load the dump stream in sbox.repo_url
763 load_and_verify_dumpstream(sbox
,[],[], None, dumpfile
)
765 # Load the dump stream in toplevel dir
766 load_and_verify_dumpstream(sbox
,[],[], None, dumpfile
, '--parent-dir',
769 # Verify the svn:mergeinfo properties
770 svntest
.actions
.run_and_verify_svn(None, ["/trunk:1-4\n"],
771 [], 'propget', 'svn:mergeinfo',
772 sbox
.repo_url
+ '/branch2')
773 svntest
.actions
.run_and_verify_svn(None, ["/branch1:5-9\n"],
774 [], 'propget', 'svn:mergeinfo',
775 sbox
.repo_url
+ '/trunk')
776 svntest
.actions
.run_and_verify_svn(None, ["/toplevel/trunk:1-13\n"],
777 [], 'propget', 'svn:mergeinfo',
778 sbox
.repo_url
+ '/toplevel/branch2')
779 svntest
.actions
.run_and_verify_svn(None, ["/toplevel/branch1:14-18\n"],
780 [], 'propget', 'svn:mergeinfo',
781 sbox
.repo_url
+ '/toplevel/trunk')
782 svntest
.actions
.run_and_verify_svn(None, ["/toplevel/trunk:1-12\n"],
783 [], 'propget', 'svn:mergeinfo',
784 sbox
.repo_url
+ '/toplevel/branch1')
785 svntest
.actions
.run_and_verify_svn(None, ["/trunk:1-3\n"],
786 [], 'propget', 'svn:mergeinfo',
787 sbox
.repo_url
+ '/branch1')
789 #----------------------------------------------------------------------
791 def fsfs_recover_handle_missing_revs_or_revprops_file(sbox
):
792 """fsfs recovery checks missing revs / revprops files"""
793 # Set up a repository containing the greek tree.
796 # Commit up to r3, so we can test various recovery scenarios.
797 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newer line\n')
798 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
800 svntest
.main
.file_append(os
.path
.join(sbox
.wc_dir
, 'iota'), 'newest line\n')
801 svntest
.main
.run_svn(None, 'ci', sbox
.wc_dir
, '--quiet', '-m', 'log msg')
803 rev_3
= fsfs_file(sbox
.repo_dir
, 'revs', '3')
804 rev_was_3
= fsfs_file(sbox
.repo_dir
, 'revs', 'was_3')
806 # Move aside the revs file for r3.
807 os
.rename(rev_3
, rev_was_3
)
809 # Verify 'svnadmin recover' fails when youngest has a revprops
810 # file but no revs file.
811 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
814 if svntest
.verify
.verify_outputs(
815 "Output of 'svnadmin recover' is unexpected.", None, errput
, None,
816 ".*Expected current rev to be <= 2 but found 3"):
817 raise svntest
.Failure
819 # Restore the r3 revs file, thus repairing the repository.
820 os
.rename(rev_was_3
, rev_3
)
822 revprop_3
= fsfs_file(sbox
.repo_dir
, 'revprops', '3')
823 revprop_was_3
= fsfs_file(sbox
.repo_dir
, 'revprops', 'was_3')
825 # Move aside the revprops file for r3.
826 os
.rename(revprop_3
, revprop_was_3
)
828 # Verify 'svnadmin recover' fails when youngest has a revs file
829 # but no revprops file (issue #2992).
830 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
833 if svntest
.verify
.verify_outputs(
834 "Output of 'svnadmin recover' is unexpected.", None, errput
, None,
835 ".*Revision 3 has a revs file but no revprops file"):
836 raise svntest
.Failure
838 # Restore the r3 revprops file, thus repairing the repository.
839 os
.rename(revprop_was_3
, revprop_3
)
841 # Change revprops file to a directory for revision 3
842 os
.rename(revprop_3
, revprop_was_3
)
845 # Verify 'svnadmin recover' fails when youngest has a revs file
846 # but revprops file is not a file (another aspect of issue #2992).
847 exit_code
, output
, errput
= svntest
.main
.run_svnadmin("recover",
850 if svntest
.verify
.verify_outputs(
851 "Output of 'svnadmin recover' is unexpected.", None, errput
, None,
852 ".*Revision 3 has a non-file where its revprops file should be.*"):
853 raise svntest
.Failure
855 ########################################################################
859 # list all tests here, starting with None:
863 inconsistent_headers
,
866 dump_move_dir_modify_child
,
871 verify_windows_paths_in_repos
,
872 SkipUnless(verify_incremental_fsfs
, svntest
.main
.is_fs_type_fsfs
),
873 SkipUnless(recover_fsfs
, svntest
.main
.is_fs_type_fsfs
),
874 load_with_parent_dir
,
876 reflect_dropped_renumbered_revs
,
877 SkipUnless(fsfs_recover_handle_missing_revs_or_revprops_file
,
878 svntest
.main
.is_fs_type_fsfs
),
881 if __name__
== '__main__':
882 svntest
.main
.run_tests(test_list
)