On 12/20/2012 11:25 PM, Julian Foad wrote:
Hi Prabhu.
I have now looked in detail at your patch and tried using it. I think I have
found an inconsistency and a serious problem.
The output for a failed revision depends on whether --keep-going was passed. With
--keep-going you print a "* Error verifying revision 2." line; without it you
don't.
Consistency of the output is important, but even more important is simplicity
of the code. I would expect the code to look something like (pseudo-code):
for R in range:
err = verify_rev(R)
if (err)
show the error and a 'Failed' notification
had_error = TRUE
if not keep_going:
break
if had_error:
return a 'Failed to verify the repo' error
but
you seem to have several different code paths. Why do you have two
different places that generate the "Repository '%s' failed to verify"
message; can you do it in just one place?
Yeah Julian, now the code generates the "Repository '%s' failed to
verify" message only in one place, thanks for the idea.
Another justification for always printing the "* Error verifying revision 2."
line is that with the old output:
[[[
$ svnadmin verify repo
...
* Verified revision 15921.
* Verified revision 15922.
* Verified revision 15923.
svnadmin: E160004: Invalid change kind in rev file
]]]
it
can be a little confusing at first glance to realize that the error
relates to a revision number that was not mentioned -- revision 15924 in this
example. I have often in the past wished that we would print a
notification line like "* Error verifying revision 15924." here.
Also, in email [1] I suggested
that the final summary error should be printed even when keep-going is
false. Did you consider that suggestion? What do you think?
Yeah I have taken that into consideration and implemented it as well.
<snip>
$ svnadmin verify repo2
* Verified revision 0.
* Verified revision 1.
* Error verifying revision 2.
svnadmin: E160004: Invalid change kind in rev file
svnadmin: E165005: Repository 'repo2' failed to verify
$ echo $?
1
</snip>
A more serious problem: it doesn't always report the error at the end.
[[[
$ bin/svnadmin verify --keep-going repo2
* Verified revision 0.
* Verified revision 1.
* Error verifying revision 2.
subversion/libsvn_repos/replay.c:859: (apr_err=160004)
subversion/libsvn_fs_fs/fs_fs.c:6335: (apr_err=160004)
subversion/libsvn_fs_fs/fs_fs.c:6311: (apr_err=160004)
subversion/libsvn_fs_fs/fs_fs.c:6242: (apr_err=160004)
subversion/libsvn_fs_fs/fs_fs.c:6065: (apr_err=160004)
svnadmin: E160004: Invalid change kind in rev file
* Verified revision 3.
]]]
The exit code is 0 here. Clearly a bug. The repository I used for this test
is attached as 'jaf-corrupt-repo-2.tgz'.
Ahh, I missed out a code when moving my code from main.c to svnadmin.c
(sorry about that). This works fine now.
<snip>
$ svnadmin verify repo2 --keep-going
* Verified revision 0.
* Verified revision 1.
* Error verifying revision 2.
svnadmin: E160004: Invalid change kind in rev file
* Verified revision 3.
svnadmin: E165005: Repository 'repo2' failed to verify
$ echo $?
1
</snip>
I am now sure that you need more tests. You added a test, but can you tell us
what it tests in functional terms? It looks like it tests verifying a repo
where there is an error in r6, and the youngest rev is r6. That doesn't cover
the main purpose of the 'keep going' feature, which is to keep going, does it?
Can you think of other things that should be tested? Please write a short list
of tests that we should ideally have -- even if we might not write them all.
It might start with something like:
Scenario 1:
Repo: youngest=r3, an error in r3.
Command: svnadmin verify --keep-going repo
Expected results:
stdout: Nothing
stderr: Success messages for r0, r1, r2.
A 'revision failed' message for r3.
At least one error message relating to r3.
exit code: non-zero.
Scenario 2:
Repo: youngest=r3, an error in r2
Command: svnadmin verify repo
Expected results:
stdout: nothing
stderr: Success for r1
Revision failed message for r2
Error message relating to r2
Repository %s failed to verify message
exit code: non-zero
Scenario 3:
Repo: youngest=r3, an error in r2
Command: svnadmin verify repo --keep-going
Expected results:
stdout: nothing
stderr: Success for r1
Revision failed message for r2
Error message relating to r2
Success for r3
Repository %s failed to verify message
exit code: non-zero
Scenario 4:
Repo: youngest=r3, an error in r3
Command: svnadmin verify repo -r1:2
Expected results:
stdout: nothing
stderr: Success for r1, r2
exit code: zero
Scenario 5:
Repo: youngest=r3, an error in r3
Command: svnadmin verify repo -r1:2 --keep-going
Expected results:
stdout: nothing
stderr: Success for r1, r2
exit code: zero
Scenario 2:
Repo: youngest=r5, error in r3 only (not affecting r4 or r5)
Command: svnadmin verify --keep-going repo
Expected results:
...
In svn_repos.h: svn_repos_verify_fs3():
/**
* Verify the contents of the file system in @a repos.
*
* If @a feedback_stream is not @c NULL, write feedback to it (lines of
* the form "* Verified revision %ld\n").
This mentions what feedback the function gives. You are adding new feedback,
so please update the doc string. It must be out of date already because the
function doesn't have a 'feedback_stream' parameter, so please fix that at the
same time.
Updated the doc string...
* If @a start_rev is #SVN_INVALID_REVNUM, then start verifying at
* revision 0. If @a end_rev is #SVN_INVALID_REVNUM, then verify
* through the @c HEAD revision.
*
* For every verified revision call @a notify_func with @a rev set to
* the verified revision and @a warning_text @c NULL. For warnings call @a
* notify_func with @a warning_text set.
Is that paragraph still correct or does it need updating?
Updated the paragraph...
+ * If @a keep_going is @c TRUE, the verify process notifies the error message
+ * and continues. If @a notify_func is @c NULL, the verification failure is
+ * not notified.
Please document what this function returns (as I asked in [2]).
Yeah sure, documented the changes
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_repos_verify_fs3(svn_repos_t *repos, ...);
In subversion/libsvn_repos/dump.c: svn_repos_verify_fs3():
You are doing error detection and handling in two places in this function out of
more than two possible places where an error could be thrown. As I wrote in [3],
"Instead of checking for errors in several places within the main loop,
put the verification code in a wrapper function and check for errors
exactly once where you call that function. That way you won't miss
any. In your last patch, there is at least one call that could return a
verification error that isn't checked -- the call to
svn_fs_revision_root()."
Yeah I get that, sounds a good idea :)
Now used a new wrapper function verification_checks() to perform all the
error checks, thus catching any possible error in one shot.
In svnadmin.c:
+ case svn_repos_notify_failure:
+ if (notify->revision != SVN_INVALID_REVNUM)
+ svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool,
+ ("* Error verifying revision %ld.\n"),
+ notify->revision));
The message needs _() not just () around it for localization.
oops, I get it... Updated the code...
Attaching the updated patch and the log message with this mail. Please
share your views..
Thanks and regards
Prabhu
(The feature has been rightly name "keep-going", so does it :) )
Implement svnadmin verify --keep-going, which would continue the verification
even if there is some corruption, after printing the errors to stderr.
* subversion/svnadmin/svnadmin.c
(svnadmin__cmdline_options_t): Add keep-going option.
(svnadmin_opt_state): Add keep-going option.
(subcommand_verify): Switch to the new svn_repos_verify_fs3 function instead
of svn_repos_verify_fs2, and pass the keep-going option.
(repos_notify_handler): Handle svn_repos_notify_failure notification by
printing warnings to stderr with the respective revision number.
* subversion/include/svn_repos.h
(svn_repos_notify_action_t): Add svn_repos_notify_failure to notify failure.
(svn_repos_verify_fs3): Newly added to handle "keep-going" option.
(svn_repos_notify_t): Add "err", the error chain which indicates what went
wrong during verification.
* subversion/libsvn_repos/dump.c
(svn_repos_verify_fs3): Handle "keep-going". If "keep-going" is TRUE, the
error message is notified and verification process continues.
When a repository fails to verify, return an SVN_ERR_REPOS_CORRUPTED error
message and return a non-zero exit code.
(notify_verification_error): New function to notify the verification
failure error message.
(verification_checks): New wrapper function to perform all the error checks for
a particular revision in one go.
* subversion/libsvn_repos/deprecated.c
(svn_repos_verify_fs2): Deprecate. Call svn_repos_verify_fs3 with
keep_going as FALSE by default to keep the old default implementation.
* subversion/tests/cmdline/svnadmin_tests.py
(verify_keep_going): New test case to test svnadmin verify and the new
switch --keep-going.
Patch by: Prabhu Gnana Sundar <prabhugs{_AT_}collab.net>
Index: subversion/svnadmin/svnadmin.c
===================================================================
--- subversion/svnadmin/svnadmin.c (revision 1427745)
+++ subversion/svnadmin/svnadmin.c (working copy)
@@ -175,6 +175,7 @@ enum svnadmin__cmdline_options_t
{
svnadmin__version = SVN_OPT_FIRST_LONGOPT_ID,
svnadmin__incremental,
+ svnadmin__keep_going,
svnadmin__deltas,
svnadmin__ignore_uuid,
svnadmin__force_uuid,
@@ -280,6 +281,9 @@ static const apr_getopt_option_t options_table[] =
{"pre-1.6-compatible", svnadmin__pre_1_6_compatible, 0,
N_("deprecated; see --compatible-version")},
+ {"keep-going", svnadmin__keep_going, 0,
+ N_("continue verifying after detecting a corruption")},
+
{"memory-cache-size", 'M', 1,
N_("size of the extra in-memory cache in MB used to\n"
" minimize redundant operations. Default: 16.\n"
@@ -471,7 +475,7 @@ static const svn_opt_subcommand_desc2_t cmd_table[
{"verify", subcommand_verify, {0}, N_
("usage: svnadmin verify REPOS_PATH\n\n"
"Verifies the data stored in the repository.\n"),
- {'r', 'q', 'M'} },
+ {'r', 'q', svnadmin__keep_going, 'M'} },
{ NULL, NULL, {0}, NULL, {0} }
};
@@ -501,6 +505,7 @@ struct svnadmin_opt_state
svn_boolean_t clean_logs; /* --clean-logs */
svn_boolean_t bypass_hooks; /* --bypass-hooks */
svn_boolean_t wait; /* --wait */
+ svn_boolean_t keep_going; /* --keep-going */
svn_boolean_t bypass_prop_validation; /* --bypass-prop-validation */
enum svn_repos_load_uuid uuid_action; /* --ignore-uuid,
--force-uuid */
@@ -744,6 +749,16 @@ repos_notify_handler(void *baton,
notify->warning_str));
return;
+ case svn_repos_notify_failure:
+ if (notify->revision != SVN_INVALID_REVNUM)
+ svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool,
+ _("* Error verifying revision %ld.\n"),
+ notify->revision));
+ if (notify->err)
+ svn_handle_error2(notify->err, stderr, FALSE /* non-fatal */,
+ "svnadmin: ");
+ return;
+
case svn_repos_notify_dump_rev_end:
svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool,
_("* Dumped revision %ld.\n"),
@@ -1533,10 +1548,12 @@ subcommand_verify(apr_getopt_t *os, void *baton, a
if (! opt_state->quiet)
progress_stream = recode_stream_create(stderr, pool);
- return svn_repos_verify_fs2(repos, lower, upper,
- !opt_state->quiet
- ? repos_notify_handler : NULL,
- progress_stream, check_cancel, NULL, pool);
+ return svn_error_trace(svn_repos_verify_fs3(repos, lower, upper,
+ opt_state->keep_going,
+ !opt_state->quiet
+ ? repos_notify_handler : NULL,
+ progress_stream, check_cancel,
+ NULL, pool));
}
/* This implements `svn_opt_subcommand_t'. */
@@ -2032,6 +2049,9 @@ sub_main(int argc, const char *argv[], apr_pool_t
opt_state.compatible_version = compatible_version;
}
break;
+ case svnadmin__keep_going:
+ opt_state.keep_going = TRUE;
+ break;
case svnadmin__fs_type:
SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.fs_type, opt_arg, pool));
break;
Index: subversion/tests/cmdline/svnadmin_tests.py
===================================================================
--- subversion/tests/cmdline/svnadmin_tests.py (revision 1427745)
+++ subversion/tests/cmdline/svnadmin_tests.py (working copy)
@@ -1835,6 +1835,107 @@ def recover_old(sbox):
svntest.main.run_svnadmin("recover", sbox.repo_dir)
+def verify_keep_going(sbox):
+ "svnadmin verify --keep-going test"
+ test_create(sbox)
+ dumpfile_skeleton = open(os.path.join(os.path.dirname(sys.argv[0]),
+ 'svnadmin_tests_data',
+ 'skeleton_repos.dump')).read()
+ load_dumpstream(sbox, dumpfile_skeleton, '--ignore-uuid')
+
+ r6 = fsfs_file(sbox.repo_dir, 'revs', '6')
+ fp = open(r6, 'wb')
+ fp.write("""id: 3-6.0.r6/0
+type: file
+count: 0
+text: 2 0 60 48 02d086e41b03058c5f1af6282c1f483f cc67e4dd7cd8ca83095c8b95f65b6698b39cb263 5-5/_5
+props: 2 73 34 0 25e6c2f7558b7484000d4d090dea5b92
+cpath: /Projects/docs/README
+copyroot: 0 /
+
+PLAIN
+K 6
+README
+V 15
+file 3-6.0.r6/0
+END
+ENDREP
+id: 1-6.0.r6/275
+type: dir
+count: 0
+text: 6 226 36 0 2c3f6410944c6ff8667fa1b3e78f45a2
+cpath: /Projects/docs
+copyroot: 0 /
+
+PLAIN
+K 9
+Project-X
+V 14
+dir 1-3.0.r3/0
+K 9
+Project-Y
+V 14
+dir 1-4.0.r4/0
+K 9
+Project-Z
+V 14
+dir 1-5.0.r5/0
+K 4
+docs
+V 16
+dir 1-6.0.r6/275
+END
+ENDREP
+id: 0-1.0.r6/548
+type: dir
+pred: 0-1.0.r5/195
+count: 4
+text: 6 398 137 0 c758f548da93cc57d68af0610766b549
+cpath: /Projects
+copyroot: 0 /
+
+PLAIN
+K 8
+Projects
+V 16
+dir 0-1.0.r6/548
+K 6
+README
+V 17
+file 0-2.0.r2/120
+END
+ENDREP
+id: 0.0.r6/772
+type: dir
+pred: 0.0.r5/418
+count: 6
+text: 6 686 73 0 353c6bbf43b0f2ae474d85e206337bbd
+cpath: /
+copyroot: 0 /
+
+_1.0.t5-5 add-dir false false /Projects/docs
+
+_3.0.t5-5 add-file true true /Projects/docs/README
+
+
+""")
+ fp.close()
+ exit_code, output, errput = svntest.main.run_svnadmin("verify",
+ sbox.repo_dir)
+ exit_code, output, errput2 = svntest.main.run_svnadmin("verify",
+ "--keep-going",
+ sbox.repo_dir)
+
+ if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
+ [], errput, None, ".*svnadmin: E165005: .*"):
+ raise svntest.Failure
+
+ # The last line of the rev 6 file is made blank to corrupt it.
+ # And hence the error "Could not convert '' into a number
+ if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
+ [], errput2, None, ".*svnadmin: E165005: .*"):
+ raise svntest.Failure
+
########################################################################
# Run the tests
@@ -1871,6 +1972,7 @@ test_list = [ None,
locking,
mergeinfo_race,
recover_old,
+ verify_keep_going,
]
if __name__ == '__main__':
Index: subversion/libsvn_repos/deprecated.c
===================================================================
--- subversion/libsvn_repos/deprecated.c (revision 1427745)
+++ subversion/libsvn_repos/deprecated.c (working copy)
@@ -728,6 +728,27 @@ svn_repos_dump_fs2(svn_repos_t *repos,
}
svn_error_t *
+svn_repos_verify_fs2(svn_repos_t *repos,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_repos_verify_fs3(repos,
+ start_rev,
+ end_rev,
+ FALSE,
+ notify_func,
+ notify_baton,
+ cancel_func,
+ cancel_baton,
+ pool));
+}
+
+svn_error_t *
svn_repos_verify_fs(svn_repos_t *repos,
svn_stream_t *feedback_stream,
svn_revnum_t start_rev,
Index: subversion/libsvn_repos/dump.c
===================================================================
--- subversion/libsvn_repos/dump.c (revision 1427745)
+++ subversion/libsvn_repos/dump.c (working copy)
@@ -1359,10 +1359,75 @@ verify_close_directory(void *dir_baton,
return close_directory(dir_baton, pool);
}
+static void
+notify_verification_error(svn_revnum_t rev,
+ svn_error_t *err,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *pool)
+{
+ if (notify_func)
+ {
+ svn_repos_notify_t *notify_failure;
+ notify_failure = svn_repos_notify_create(svn_repos_notify_failure, pool);
+ notify_failure->err = err;
+ notify_failure->revision = rev;
+ notify_func(notify_baton, notify_failure, pool);
+ }
+}
+
svn_error_t *
-svn_repos_verify_fs2(svn_repos_t *repos,
+verification_checks(svn_fs_t *fs,
+ svn_revnum_t rev,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_revnum_t start_rev,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *iterpool)
+{
+ const svn_delta_editor_t *dump_editor;
+ void *dump_edit_baton;
+
+ svn_fs_root_t *to_root;
+ apr_hash_t *props;
+ const svn_delta_editor_t *cancel_editor;
+ void *cancel_edit_baton;
+
+ /* Get cancellable dump editor, but with our close_directory handler. */
+ SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton,
+ fs, rev, "",
+ svn_stream_empty(iterpool),
+ NULL, NULL,
+ verify_close_directory,
+ notify_func, notify_baton,
+ start_rev,
+ FALSE, TRUE, /* use_deltas, verify */
+ iterpool));
+ SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
+ dump_editor, dump_edit_baton,
+ &cancel_editor,
+ &cancel_edit_baton,
+ iterpool));
+
+ SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool));
+ SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
+ cancel_editor, cancel_edit_baton,
+ NULL, NULL, iterpool));
+
+ /* While our editor close_edit implementation is a no-op, we still
+ do this for completeness. */
+ SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, iterpool));
+
+ SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, iterpool));
+
+}
+
+svn_error_t *
+svn_repos_verify_fs3(svn_repos_t *repos,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
+ svn_boolean_t keep_going,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
@@ -1374,6 +1439,8 @@ svn_error_t *
svn_revnum_t rev;
apr_pool_t *iterpool = svn_pool_create(pool);
svn_repos_notify_t *notify;
+ svn_error_t *err;
+ svn_boolean_t found_corruption = FALSE;
/* Determine the current youngest revision of the filesystem. */
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -1397,8 +1464,27 @@ svn_error_t *
end_rev, youngest);
/* Verify global/auxiliary data and backend-specific data first. */
- SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
- start_rev, end_rev, pool));
+ err = svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
+ start_rev, end_rev, pool);
+ if (err && !keep_going)
+ {
+ rev = SVN_INVALID_REVNUM;
+ found_corruption = TRUE;
+ notify_verification_error(rev, err, notify_func, notify_baton,
+ iterpool);
+ svn_error_clear(err);
+ return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
+ _("Repository '%s' failed to verify"),
+ svn_dirent_local_style(svn_repos_path(repos,
+ pool),
+ pool));
+ }
+ else
+ {
+ if (err)
+ found_corruption = TRUE;
+ svn_error_clear(err);
+ }
/* Create a notify object that we can reuse within the loop. */
if (notify_func)
@@ -1407,41 +1493,32 @@ svn_error_t *
for (rev = start_rev; rev <= end_rev; rev++)
{
- const svn_delta_editor_t *dump_editor;
- void *dump_edit_baton;
- const svn_delta_editor_t *cancel_editor;
- void *cancel_edit_baton;
- svn_fs_root_t *to_root;
- apr_hash_t *props;
+ svn_error_t *err;
svn_pool_clear(iterpool);
- /* Get cancellable dump editor, but with our close_directory handler. */
- SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton,
- fs, rev, "",
- svn_stream_empty(iterpool),
- NULL, NULL,
- verify_close_directory,
- notify_func, notify_baton,
- start_rev,
- FALSE, TRUE, /* use_deltas, verify */
- iterpool));
- SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
- dump_editor, dump_edit_baton,
- &cancel_editor,
- &cancel_edit_baton,
- iterpool));
+ /* Wrapper function to catch the possible errors. */
+ err = verification_checks(fs, rev, notify_func, notify_baton, start_rev,
+ cancel_func, cancel_baton, iterpool);
- SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool));
- SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
- cancel_editor, cancel_edit_baton,
- NULL, NULL, iterpool));
- /* While our editor close_edit implementation is a no-op, we still
- do this for completeness. */
- SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, iterpool));
+ if (err && keep_going)
+ {
+ found_corruption = TRUE;
+ notify_verification_error(rev, err, notify_func, notify_baton,
+ iterpool);
+ svn_error_clear(err);
+ continue;
+ }
+ else
+ if (err)
+ {
+ found_corruption = TRUE;
+ notify_verification_error(rev, err, notify_func, notify_baton,
+ iterpool);
+ svn_error_clear(err);
+ break;
+ }
- SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, iterpool));
-
if (notify_func)
{
notify->revision = rev;
@@ -1459,5 +1536,11 @@ svn_error_t *
/* Per-backend verification. */
svn_pool_destroy(iterpool);
+ if (found_corruption)
+ return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
+ _("Repository '%s' failed to verify"),
+ svn_dirent_local_style(svn_repos_path(repos,
+ pool),
+ pool));
return SVN_NO_ERROR;
}
Index: subversion/include/svn_error_codes.h
===================================================================
--- subversion/include/svn_error_codes.h (revision 1427745)
+++ subversion/include/svn_error_codes.h (working copy)
@@ -814,6 +814,10 @@ SVN_ERROR_START
SVN_ERR_REPOS_CATEGORY_START + 4,
"Bogus revision report")
+ SVN_ERRDEF(SVN_ERR_REPOS_CORRUPTED,
+ SVN_ERR_REPOS_CATEGORY_START + 5,
+ "Repository has corruptions")
+
/* This is analogous to SVN_ERR_FS_UNSUPPORTED_FORMAT. To avoid
* confusion with "versions" (i.e., releases) of Subversion, we
* started using the word "format" instead of "version". However,
Index: subversion/include/svn_repos.h
===================================================================
--- subversion/include/svn_repos.h (revision 1427745)
+++ subversion/include/svn_repos.h (working copy)
@@ -245,8 +245,11 @@ typedef enum svn_repos_notify_action_t
svn_repos_notify_upgrade_start,
/** A revision was skipped during loading. @since New in 1.8. */
- svn_repos_notify_load_skipped_rev
+ svn_repos_notify_load_skipped_rev,
+ /** A revision is found with corruption/errors. @since New in 1.8. */
+ svn_repos_notify_failure
+
} svn_repos_notify_action_t;
/** The type of error occurring.
@@ -318,6 +321,11 @@ typedef struct svn_repos_notify_t
/** For #svn_repos_notify_load_node_start, the path of the node. */
const char *path;
+ /** For #svn_repos_notify_failure, this error chain indicates what
+ went wrong during verification.
+ @since New in 1.8. */
+ svn_error_t *err;
+
/* NOTE: Add new fields at the end to preserve binary compatibility.
Also, if you add fields here, you have to update
svn_repos_notify_create(). */
@@ -2503,8 +2511,9 @@ svn_repos_node_from_baton(void *edit_baton);
/**
* Verify the contents of the file system in @a repos.
*
- * If @a feedback_stream is not @c NULL, write feedback to it (lines of
- * the form "* Verified revision %ld\n").
+ * If @a notify_func is not @c NULL, write feedback to it (lines of
+ * the form "* Verified revision %ld\n". If an error/corruption is found,
+ * the feedback is of the form "* Error verifying revision %ld\n").
*
* If @a start_rev is #SVN_INVALID_REVNUM, then start verifying at
* revision 0. If @a end_rev is #SVN_INVALID_REVNUM, then verify
@@ -2513,13 +2522,38 @@ svn_repos_node_from_baton(void *edit_baton);
* For every verified revision call @a notify_func with @a rev set to
* the verified revision and @a warning_text @c NULL. For warnings call @a
* notify_func with @a warning_text set.
+ *
+ * For every revision verification failure call notify_verification_error
+ * with @a rev set to the corrupt revision.
*
* If @a cancel_func is not @c NULL, call it periodically with @a
* cancel_baton as argument to see if the caller wishes to cancel the
* verification.
*
+ * If @a keep_going is @c TRUE, the verify process notifies the error message
+ * and continues. If @a notify_func is @c NULL, the verification failure is
+ * not notified. Upon successful completion of verification, return SVN_NO_ERROR
+ * else return the corresponding failure.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_repos_verify_fs3(svn_repos_t *repos,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_boolean_t keep_going,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Like svn_repos_verify_fs3(), but with @a keep_going set to @c FALSE.
* @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_repos_verify_fs2(svn_repos_t *repos,
svn_revnum_t start_rev,