aboutsummaryrefslogtreecommitdiffstats
path: root/subversion/svnadmin/svnadmin.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svnadmin/svnadmin.c')
-rw-r--r--subversion/svnadmin/svnadmin.c473
1 files changed, 364 insertions, 109 deletions
diff --git a/subversion/svnadmin/svnadmin.c b/subversion/svnadmin/svnadmin.c
index eb26c5a8f0fc..949ed4247345 100644
--- a/subversion/svnadmin/svnadmin.c
+++ b/subversion/svnadmin/svnadmin.c
@@ -42,6 +42,7 @@
#include "svn_time.h"
#include "svn_user.h"
#include "svn_xml.h"
+#include "svn_fs.h"
#include "private/svn_cmdline_private.h"
#include "private/svn_opt_private.h"
@@ -49,6 +50,7 @@
#include "private/svn_subr_private.h"
#include "private/svn_cmdline_private.h"
#include "private/svn_fspath.h"
+#include "private/svn_fs_fs_private.h"
#include "svn_private_config.h"
@@ -95,6 +97,7 @@ check_lib_versions(void)
/** Subcommands. **/
static svn_opt_subcommand_t
+ subcommand_build_repcache,
subcommand_crashtest,
subcommand_create,
subcommand_delrevprop,
@@ -114,6 +117,7 @@ static svn_opt_subcommand_t
subcommand_lstxns,
subcommand_pack,
subcommand_recover,
+ subcommand_rev_size,
subcommand_rmlocks,
subcommand_rmtxns,
subcommand_setlog,
@@ -301,47 +305,69 @@ static const apr_getopt_option_t options_table[] =
/* Array of available subcommands.
* The entire list must be terminated with an entry of nulls.
*/
-static const svn_opt_subcommand_desc2_t cmd_table[] =
+static const svn_opt_subcommand_desc3_t cmd_table[] =
{
- {"crashtest", subcommand_crashtest, {0}, N_
- ("usage: svnadmin crashtest REPOS_PATH\n\n"
+ {"build-repcache", subcommand_build_repcache, {0}, {N_(
+ "usage: svnadmin build-repcache REPOS_PATH [-r LOWER[:UPPER]]\n"
+ "\n"), N_(
+ "Add missing entries to the representation cache for the repository\n"
+ "at REPOS_PATH. Process data in revisions LOWER through UPPER.\n"
+ "If no revision arguments are given, process all revisions. If only\n"
+ "LOWER revision argument is given, process only that single revision.\n"
+ )},
+ {'r', 'q', 'M'} },
+
+ {"crashtest", subcommand_crashtest, {0}, {N_(
+ "usage: svnadmin crashtest REPOS_PATH\n"
+ "\n"), N_(
"Open the repository at REPOS_PATH, then abort, thus simulating\n"
- "a process that crashes while holding an open repository handle.\n"),
+ "a process that crashes while holding an open repository handle.\n"
+ )},
{0} },
- {"create", subcommand_create, {0}, N_
- ("usage: svnadmin create REPOS_PATH\n\n"
- "Create a new, empty repository at REPOS_PATH.\n"),
+ {"create", subcommand_create, {0}, {N_(
+ "usage: svnadmin create REPOS_PATH\n"
+ "\n"), N_(
+ "Create a new, empty repository at REPOS_PATH.\n"
+ )},
{svnadmin__bdb_txn_nosync, svnadmin__bdb_log_keep,
svnadmin__config_dir, svnadmin__fs_type, svnadmin__compatible_version,
svnadmin__pre_1_4_compatible, svnadmin__pre_1_5_compatible,
svnadmin__pre_1_6_compatible
} },
- {"delrevprop", subcommand_delrevprop, {0}, N_
- ("usage: 1. svnadmin delrevprop REPOS_PATH -r REVISION NAME\n"
- " 2. svnadmin delrevprop REPOS_PATH -t TXN NAME\n\n"
- "1. Delete the property NAME on revision REVISION.\n\n"
+ {"delrevprop", subcommand_delrevprop, {0}, {N_(
+ "usage: 1. svnadmin delrevprop REPOS_PATH -r REVISION NAME\n"
+ " 2. svnadmin delrevprop REPOS_PATH -t TXN NAME\n"
+ "\n"), N_(
+ "1. Delete the property NAME on revision REVISION.\n"
+ "\n"), N_(
"Use --use-pre-revprop-change-hook/--use-post-revprop-change-hook to\n"
"trigger the revision property-related hooks (for example, if you want\n"
- "an email notification sent from your post-revprop-change hook).\n\n"
+ "an email notification sent from your post-revprop-change hook).\n"
+ "\n"), N_(
"NOTE: Revision properties are not versioned, so this command will\n"
- "irreversibly destroy the previous value of the property.\n\n"
- "2. Delete the property NAME on transaction TXN.\n"),
+ "irreversibly destroy the previous value of the property.\n"
+ "\n"), N_(
+ "2. Delete the property NAME on transaction TXN.\n"
+ )},
{'r', 't', svnadmin__use_pre_revprop_change_hook,
svnadmin__use_post_revprop_change_hook} },
- {"deltify", subcommand_deltify, {0}, N_
- ("usage: svnadmin deltify [-r LOWER[:UPPER]] REPOS_PATH\n\n"
+ {"deltify", subcommand_deltify, {0}, {N_(
+ "usage: svnadmin deltify [-r LOWER[:UPPER]] REPOS_PATH\n"
+ "\n"), N_(
"Run over the requested revision range, performing predecessor delti-\n"
"fication on the paths changed in those revisions. Deltification in\n"
"essence compresses the repository by only storing the differences or\n"
"delta from the preceding revision. If no revisions are specified,\n"
- "this will simply deltify the HEAD revision.\n"),
+ "this will simply deltify the HEAD revision.\n"
+ )},
{'r', 'q', 'M'} },
- {"dump", subcommand_dump, {0}, N_
- ("usage: svnadmin dump REPOS_PATH [-r LOWER[:UPPER] [--incremental]]\n\n"
+ {"dump", subcommand_dump, {0}, {N_(
+ "usage: svnadmin dump REPOS_PATH [-r LOWER[:UPPER] [--incremental]]\n"
+ "\n"), N_(
"Dump the contents of filesystem to stdout in a 'dumpfile'\n"
"portable format, sending feedback to stderr. Dump revisions\n"
"LOWER rev through UPPER rev. If no revisions are given, dump all\n"
@@ -351,73 +377,94 @@ static const svn_opt_subcommand_desc2_t cmd_table[] =
"every path present in the repository as of that revision. (In either\n"
"case, the second and subsequent revisions, if any, describe only paths\n"
"changed in those revisions.)\n"
- "\n"
+ "\n"), N_(
"Using --exclude or --include gives results equivalent to authz-based\n"
"path exclusions. In particular, when the source of a copy is\n"
- "excluded, the copy is transformed into an add (unlike in 'svndumpfilter').\n"),
+ "excluded, the copy is transformed into an add (unlike in 'svndumpfilter').\n"
+ )},
{'r', svnadmin__incremental, svnadmin__deltas, 'q', 'M', 'F',
svnadmin__exclude, svnadmin__include, svnadmin__glob },
{{'F', N_("write to file ARG instead of stdout")}} },
- {"dump-revprops", subcommand_dump_revprops, {0}, N_
- ("usage: svnadmin dump-revprops REPOS_PATH [-r LOWER[:UPPER]]\n\n"
+ {"dump-revprops", subcommand_dump_revprops, {0}, {N_(
+ "usage: svnadmin dump-revprops REPOS_PATH [-r LOWER[:UPPER]]\n"
+ "\n"), N_(
"Dump the revision properties of filesystem to stdout in a 'dumpfile'\n"
"portable format, sending feedback to stderr. Dump revisions\n"
"LOWER rev through UPPER rev. If no revisions are given, dump the\n"
"properties for all revisions. If only LOWER is given, dump the\n"
- "properties for that one revision.\n"),
+ "properties for that one revision.\n"
+ )},
{'r', 'q', 'F'},
{{'F', N_("write to file ARG instead of stdout")}} },
- {"freeze", subcommand_freeze, {0}, N_
- ("usage: 1. svnadmin freeze REPOS_PATH PROGRAM [ARG...]\n"
- " 2. svnadmin freeze -F FILE PROGRAM [ARG...]\n\n"
+ {"freeze", subcommand_freeze, {0}, {N_(
+ "usage: 1. svnadmin freeze REPOS_PATH -- PROGRAM [ARG...]\n"
+ " 2. svnadmin freeze -F FILE -- PROGRAM [ARG...]\n"
+ "\n"), N_(
"1. Run PROGRAM passing ARGS while holding a write-lock on REPOS_PATH.\n"
" Allows safe use of third-party backup tools on a live repository.\n"
- "\n"
+ "\n"), N_(
"2. Like 1 except all repositories listed in FILE are locked. The file\n"
" format is repository paths separated by newlines. Repositories are\n"
- " locked in the same order as they are listed in the file.\n"),
+ " locked in the same order as they are listed in the file.\n"
+ "\n"
+ "The '--' tells svnadmin to stop looking for svnadmin options and pass\n"
+ "all later arguments to PROGRAM even if they begin with '-'.\n"
+ )},
{'F'},
{{'F', N_("read repository paths from file ARG")}} },
- {"help", subcommand_help, {"?", "h"}, N_
- ("usage: svnadmin help [SUBCOMMAND...]\n\n"
- "Describe the usage of this program or its subcommands.\n"),
+ {"help", subcommand_help, {"?", "h"}, {N_(
+ "usage: svnadmin help [SUBCOMMAND...]\n"
+ "\n"), N_(
+ "Describe the usage of this program or its subcommands.\n"
+ )},
{0} },
- {"hotcopy", subcommand_hotcopy, {0}, N_
- ("usage: svnadmin hotcopy REPOS_PATH NEW_REPOS_PATH\n\n"
+ {"hotcopy", subcommand_hotcopy, {0}, {N_(
+ "usage: svnadmin hotcopy REPOS_PATH NEW_REPOS_PATH\n"
+ "\n"), N_(
"Make a hot copy of a repository.\n"
"If --incremental is passed, data which already exists at the destination\n"
- "is not copied again. Incremental mode is implemented for FSFS repositories.\n"),
+ "is not copied again. Incremental mode is implemented for FSFS repositories.\n"
+ )},
{svnadmin__clean_logs, svnadmin__incremental, 'q'} },
- {"info", subcommand_info, {0}, N_
- ("usage: svnadmin info REPOS_PATH\n\n"
- "Print information about the repository at REPOS_PATH.\n"),
+ {"info", subcommand_info, {0}, {N_(
+ "usage: svnadmin info REPOS_PATH\n"
+ "\n"), N_(
+ "Print information about the repository at REPOS_PATH.\n"
+ )},
{0} },
- {"list-dblogs", subcommand_list_dblogs, {0}, N_
- ("usage: svnadmin list-dblogs REPOS_PATH\n\n"
- "List all Berkeley DB log files.\n\n"
+ {"list-dblogs", subcommand_list_dblogs, {0}, {N_(
+ "usage: svnadmin list-dblogs REPOS_PATH\n"
+ "\n"), N_(
+ "List all Berkeley DB log files.\n"
+ "\n"), N_(
"WARNING: Modifying or deleting logfiles which are still in use\n"
- "will cause your repository to be corrupted.\n"),
+ "will cause your repository to be corrupted.\n"
+ )},
{0} },
- {"list-unused-dblogs", subcommand_list_unused_dblogs, {0}, N_
- ("usage: svnadmin list-unused-dblogs REPOS_PATH\n\n"
- "List unused Berkeley DB log files.\n\n"),
+ {"list-unused-dblogs", subcommand_list_unused_dblogs, {0}, {N_(
+ "usage: svnadmin list-unused-dblogs REPOS_PATH\n"
+ "\n"), N_(
+ "List unused Berkeley DB log files.\n"
+ )},
{0} },
- {"load", subcommand_load, {0}, N_
- ("usage: svnadmin load REPOS_PATH\n\n"
+ {"load", subcommand_load, {0}, {N_(
+ "usage: svnadmin load REPOS_PATH\n"
+ "\n"), N_(
"Read a 'dumpfile'-formatted stream from stdin, committing\n"
"new revisions into the repository's filesystem. If the repository\n"
"was previously empty, its UUID will, by default, be changed to the\n"
"one specified in the stream. Progress feedback is sent to stdout.\n"
"If --revision is specified, limit the loaded revisions to only those\n"
- "in the dump stream whose revision numbers match the specified range.\n"),
+ "in the dump stream whose revision numbers match the specified range.\n"
+ )},
{'q', 'r', svnadmin__ignore_uuid, svnadmin__force_uuid,
svnadmin__ignore_dates,
svnadmin__use_pre_commit_hook, svnadmin__use_post_commit_hook,
@@ -426,122 +473,166 @@ static const svn_opt_subcommand_desc2_t cmd_table[] =
svnadmin__no_flush_to_disk, 'F'},
{{'F', N_("read from file ARG instead of stdin")}} },
- {"load-revprops", subcommand_load_revprops, {0}, N_
- ("usage: svnadmin load-revprops REPOS_PATH\n\n"
+ {"load-revprops", subcommand_load_revprops, {0}, {N_(
+ "usage: svnadmin load-revprops REPOS_PATH\n"
+ "\n"), N_(
"Read a 'dumpfile'-formatted stream from stdin, setting the revision\n"
"properties in the repository's filesystem. Revisions not found in the\n"
"repository will cause an error. Progress feedback is sent to stdout.\n"
"If --revision is specified, limit the loaded revisions to only those\n"
- "in the dump stream whose revision numbers match the specified range.\n"),
+ "in the dump stream whose revision numbers match the specified range.\n"
+ )},
{'q', 'r', svnadmin__force_uuid, svnadmin__normalize_props,
svnadmin__bypass_prop_validation, svnadmin__no_flush_to_disk, 'F'},
{{'F', N_("read from file ARG instead of stdin")}} },
- {"lock", subcommand_lock, {0}, N_
- ("usage: svnadmin lock REPOS_PATH PATH USERNAME COMMENT-FILE [TOKEN]\n\n"
+ {"lock", subcommand_lock, {0}, {N_(
+ "usage: svnadmin lock REPOS_PATH PATH USERNAME COMMENT-FILE [TOKEN]\n"
+ "\n"), N_(
"Lock PATH by USERNAME setting comments from COMMENT-FILE.\n"
"If provided, use TOKEN as lock token. Use --bypass-hooks to avoid\n"
- "triggering the pre-lock and post-lock hook scripts.\n"),
+ "triggering the pre-lock and post-lock hook scripts.\n"
+ )},
{svnadmin__bypass_hooks, 'q'} },
- {"lslocks", subcommand_lslocks, {0}, N_
- ("usage: svnadmin lslocks REPOS_PATH [PATH-IN-REPOS]\n\n"
+ {"lslocks", subcommand_lslocks, {0}, {N_(
+ "usage: svnadmin lslocks REPOS_PATH [PATH-IN-REPOS]\n"
+ "\n"), N_(
"Print descriptions of all locks on or under PATH-IN-REPOS (which,\n"
- "if not provided, is the root of the repository).\n"),
+ "if not provided, is the root of the repository).\n"
+ )},
{0} },
- {"lstxns", subcommand_lstxns, {0}, N_
- ("usage: svnadmin lstxns REPOS_PATH\n\n"
+ {"lstxns", subcommand_lstxns, {0}, {N_(
+ "usage: svnadmin lstxns REPOS_PATH\n"
+ "\n"), N_(
"Print the names of uncommitted transactions. With -rN skip the output\n"
"of those that have a base revision more recent than rN. Transactions\n"
"with base revisions much older than HEAD are likely to have been\n"
- "abandonded and are candidates to be removed.\n"),
+ "abandoned and are candidates to be removed.\n"
+ )},
{'r'},
{ {'r', "transaction base revision ARG"} } },
- {"pack", subcommand_pack, {0}, N_
- ("usage: svnadmin pack REPOS_PATH\n\n"
+ {"pack", subcommand_pack, {0}, {N_(
+ "usage: svnadmin pack REPOS_PATH\n"
+ "\n"), N_(
"Possibly compact the repository into a more efficient storage model.\n"
- "This may not apply to all repositories, in which case, exit.\n"),
+ "This may not apply to all repositories, in which case, exit.\n"
+ )},
{'q', 'M'} },
- {"recover", subcommand_recover, {0}, N_
- ("usage: svnadmin recover REPOS_PATH\n\n"
+ {"recover", subcommand_recover, {0}, {N_(
+ "usage: svnadmin recover REPOS_PATH\n"
+ "\n"), N_(
"Run the recovery procedure on a repository. Do this if you've\n"
"been getting errors indicating that recovery ought to be run.\n"
"Berkeley DB recovery requires exclusive access and will\n"
- "exit if the repository is in use by another process.\n"),
+ "exit if the repository is in use by another process.\n"
+ )},
{svnadmin__wait} },
- {"rmlocks", subcommand_rmlocks, {0}, N_
- ("usage: svnadmin rmlocks REPOS_PATH LOCKED_PATH...\n\n"
- "Unconditionally remove lock from each LOCKED_PATH.\n"),
+ {"rev-size", subcommand_rev_size, {0}, {N_(
+ "usage: svnadmin rev-size REPOS_PATH -r REVISION\n"
+ "\n"), N_(
+ "Print the total size in bytes of the representation on disk of\n"
+ "revision REVISION.\n"
+ "\n"), N_(
+ "The size includes revision properties and excludes FSFS indexes.\n"
+ )},
+ {'r', 'q', 'M'},
+ { {'q', "print only the size and a newline"} } },
+
+ {"rmlocks", subcommand_rmlocks, {0}, {N_(
+ "usage: svnadmin rmlocks REPOS_PATH LOCKED_PATH...\n"
+ "\n"), N_(
+ "Unconditionally remove lock from each LOCKED_PATH.\n"
+ )},
{'q'} },
- {"rmtxns", subcommand_rmtxns, {0}, N_
- ("usage: svnadmin rmtxns REPOS_PATH TXN_NAME...\n\n"
- "Delete the named transaction(s).\n"),
+ {"rmtxns", subcommand_rmtxns, {0}, {N_(
+ "usage: svnadmin rmtxns REPOS_PATH TXN_NAME...\n"
+ "\n"), N_(
+ "Delete the named transaction(s).\n"
+ )},
{'q'} },
- {"setlog", subcommand_setlog, {0}, N_
- ("usage: svnadmin setlog REPOS_PATH -r REVISION FILE\n\n"
+ {"setlog", subcommand_setlog, {0}, {N_(
+ "usage: svnadmin setlog REPOS_PATH -r REVISION FILE\n"
+ "\n"), N_(
"Set the log-message on revision REVISION to the contents of FILE. Use\n"
"--bypass-hooks to avoid triggering the revision-property-related hooks\n"
"(for example, if you do not want an email notification sent\n"
"from your post-revprop-change hook, or because the modification of\n"
"revision properties has not been enabled in the pre-revprop-change\n"
- "hook).\n\n"
+ "hook).\n"
+ "\n"), N_(
"NOTE: Revision properties are not versioned, so this command will\n"
- "overwrite the previous log message.\n"),
+ "overwrite the previous log message.\n"
+ )},
{'r', svnadmin__bypass_hooks} },
- {"setrevprop", subcommand_setrevprop, {0}, N_
- ("usage: 1. svnadmin setrevprop REPOS_PATH -r REVISION NAME FILE\n"
- " 2. svnadmin setrevprop REPOS_PATH -t TXN NAME FILE\n\n"
- "1. Set the property NAME on revision REVISION to the contents of FILE.\n\n"
+ {"setrevprop", subcommand_setrevprop, {0}, {N_(
+ "usage: 1. svnadmin setrevprop REPOS_PATH -r REVISION NAME FILE\n"
+ " 2. svnadmin setrevprop REPOS_PATH -t TXN NAME FILE\n"
+ "\n"), N_(
+ "1. Set the property NAME on revision REVISION to the contents of FILE.\n"
+ "\n"), N_(
"Use --use-pre-revprop-change-hook/--use-post-revprop-change-hook to\n"
"trigger the revision property-related hooks (for example, if you want\n"
- "an email notification sent from your post-revprop-change hook).\n\n"
+ "an email notification sent from your post-revprop-change hook).\n"
+ "\n"), N_(
"NOTE: Revision properties are not versioned, so this command will\n"
- "overwrite the previous value of the property.\n\n"
- "2. Set the property NAME on transaction TXN to the contents of FILE.\n"),
+ "overwrite the previous value of the property.\n"
+ "\n"), N_(
+ "2. Set the property NAME on transaction TXN to the contents of FILE.\n"
+ )},
{'r', 't', svnadmin__use_pre_revprop_change_hook,
svnadmin__use_post_revprop_change_hook} },
- {"setuuid", subcommand_setuuid, {0}, N_
- ("usage: svnadmin setuuid REPOS_PATH [NEW_UUID]\n\n"
+ {"setuuid", subcommand_setuuid, {0}, {N_(
+ "usage: svnadmin setuuid REPOS_PATH [NEW_UUID]\n"
+ "\n"), N_(
"Reset the repository UUID for the repository located at REPOS_PATH. If\n"
"NEW_UUID is provided, use that as the new repository UUID; otherwise,\n"
- "generate a brand new UUID for the repository.\n"),
+ "generate a brand new UUID for the repository.\n"
+ )},
{0} },
- {"unlock", subcommand_unlock, {0}, N_
- ("usage: svnadmin unlock REPOS_PATH LOCKED_PATH USERNAME TOKEN\n\n"
+ {"unlock", subcommand_unlock, {0}, {N_(
+ "usage: svnadmin unlock REPOS_PATH LOCKED_PATH USERNAME TOKEN\n"
+ "\n"), N_(
"Unlock LOCKED_PATH (as USERNAME) after verifying that the token\n"
"associated with the lock matches TOKEN. Use --bypass-hooks to avoid\n"
- "triggering the pre-unlock and post-unlock hook scripts.\n"),
+ "triggering the pre-unlock and post-unlock hook scripts.\n"
+ )},
{svnadmin__bypass_hooks, 'q'} },
- {"upgrade", subcommand_upgrade, {0}, N_
- ("usage: svnadmin upgrade REPOS_PATH\n\n"
+ {"upgrade", subcommand_upgrade, {0}, {N_(
+ "usage: svnadmin upgrade REPOS_PATH\n"
+ "\n"), N_(
"Upgrade the repository located at REPOS_PATH to the latest supported\n"
- "schema version.\n\n"
+ "schema version.\n"
+ "\n"), N_(
"This functionality is provided as a convenience for repository\n"
"administrators who wish to make use of new Subversion functionality\n"
"without having to undertake a potentially costly full repository dump\n"
"and load operation. As such, the upgrade performs only the minimum\n"
"amount of work needed to accomplish this while still maintaining the\n"
"integrity of the repository. It does not guarantee the most optimized\n"
- "repository state as a dump and subsequent load would.\n"),
+ "repository state as a dump and subsequent load would.\n"
+ )},
{0} },
- {"verify", subcommand_verify, {0}, N_
- ("usage: svnadmin verify REPOS_PATH\n\n"
- "Verify the data stored in the repository.\n"),
+ {"verify", subcommand_verify, {0}, {N_(
+ "usage: svnadmin verify REPOS_PATH\n"
+ "\n"), N_(
+ "Verify the data stored in the repository.\n"
+ )},
{'t', 'r', 'q', svnadmin__keep_going, 'M',
svnadmin__check_normalization, svnadmin__metadata_only} },
- { NULL, NULL, {0}, NULL, {0} }
+ { NULL, NULL, {0}, {NULL}, {0} }
};
@@ -1540,7 +1631,7 @@ subcommand_help(apr_getopt_t *os, void *baton, apr_pool_t *pool)
version_footer = svn_stringbuf_create(fs_desc_start, pool);
SVN_ERR(svn_fs_print_modules(version_footer, pool));
- SVN_ERR(svn_opt_print_help4(os, "svnadmin",
+ SVN_ERR(svn_opt_print_help5(os, "svnadmin",
opt_state ? opt_state->version : FALSE,
opt_state ? opt_state->quiet : FALSE,
/*###opt_state ? opt_state->verbose :*/ FALSE,
@@ -1753,7 +1844,7 @@ subcommand_lstxns(apr_getopt_t *os, void *baton, apr_pool_t *pool)
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
SVN_ERR(get_revnum(&limit, &opt_state->start_revision, youngest, repos,
pool));
-
+
iterpool = svn_pool_create(pool);
for (i = 0; i < txns->nelts; i++)
{
@@ -2191,15 +2282,16 @@ subcommand_verify(apr_getopt_t *os, void *baton, apr_pool_t *pool)
check_cancel, NULL, pool));
/* Show the --keep-going error summary. */
- if (!opt_state->quiet
- && opt_state->keep_going
- && verify_baton.error_summary->nelts > 0)
+ if (opt_state->keep_going && verify_baton.error_summary->nelts > 0)
{
int rev_maxlength;
svn_revnum_t end_revnum;
apr_pool_t *iterpool;
int i;
+ if (feedback_stream == NULL) /* happens when we are in --quiet mode */
+ feedback_stream = recode_stream_create(stdout, pool);
+
svn_error_clear(
svn_stream_puts(feedback_stream,
_("\n-----Summary of corrupt revisions-----\n")));
@@ -2780,6 +2872,169 @@ subcommand_delrevprop(apr_getopt_t *os, void *baton, apr_pool_t *pool)
}
+/* Set *REV_SIZE to the total size in bytes of the representation on disk
+ * of revision REVISION in FS.
+ *
+ * This is implemented only for FSFS repositories, and otherwise returns
+ * an SVN_ERR_UNSUPPORTED_FEATURE error.
+ *
+ * The size includes revision properties and excludes FSFS indexes.
+ */
+static svn_error_t *
+revision_size(apr_off_t *rev_size,
+ svn_fs_t *fs,
+ svn_revnum_t revision,
+ apr_pool_t *scratch_pool)
+{
+ svn_error_t *err;
+ svn_fs_fs__ioctl_revision_size_input_t input = {0};
+ svn_fs_fs__ioctl_revision_size_output_t *output;
+
+ input.revision = revision;
+ err = svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_REVISION_SIZE,
+ &input, (void **)&output,
+ check_cancel, NULL, scratch_pool, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE)
+ {
+ return svn_error_quick_wrapf(err,
+ _("Revision size query is not implemented "
+ "for the filesystem type found in '%s'"),
+ svn_fs_path(fs, scratch_pool));
+ }
+ SVN_ERR(err);
+
+ *rev_size = output->rev_size;
+ return SVN_NO_ERROR;
+}
+
+/* This implements `svn_opt_subcommand_t'. */
+svn_error_t *
+subcommand_rev_size(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ struct svnadmin_opt_state *opt_state = baton;
+ svn_revnum_t revision;
+ apr_off_t rev_size;
+ svn_repos_t *repos;
+
+ if (opt_state->start_revision.kind != svn_opt_revision_number
+ || opt_state->end_revision.kind != svn_opt_revision_unspecified)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Invalid revision specifier"));
+ revision = opt_state->start_revision.value.number;
+
+ SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool));
+ SVN_ERR(revision_size(&rev_size, svn_repos_fs(repos), revision, pool));
+
+ if (opt_state->quiet)
+ SVN_ERR(svn_cmdline_printf(pool, "%"APR_OFF_T_FMT"\n", rev_size));
+ else
+ SVN_ERR(svn_cmdline_printf(pool, _("%12"APR_OFF_T_FMT" bytes in revision %ld\n"),
+ rev_size, revision));
+
+ return SVN_NO_ERROR;
+}
+
+static void
+build_rep_cache_progress_func(svn_revnum_t revision,
+ void *baton,
+ apr_pool_t *pool)
+{
+ svn_error_clear(svn_cmdline_printf(pool,
+ _("* Processed revision %ld.\n"),
+ revision));
+}
+
+static svn_error_t *
+build_rep_cache(svn_fs_t *fs,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ struct svnadmin_opt_state *opt_state,
+ apr_pool_t *pool)
+{
+ svn_fs_fs__ioctl_build_rep_cache_input_t input = {0};
+ svn_error_t *err;
+
+ input.start_rev = start_rev;
+ input.end_rev = end_rev;
+
+ if (opt_state->quiet)
+ {
+ input.progress_func = NULL;
+ input.progress_baton = NULL;
+ }
+ else
+ {
+ input.progress_func = build_rep_cache_progress_func;
+ input.progress_baton = NULL;
+ }
+
+ err = svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_BUILD_REP_CACHE,
+ &input, NULL,
+ check_cancel, NULL, pool, pool);
+ if (err && err->apr_err == SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE)
+ {
+ return svn_error_quick_wrapf(err,
+ _("Building rep-cache is not implemented "
+ "for the filesystem type found in '%s'"),
+ svn_fs_path(fs, pool));
+ }
+ else if (err && err->apr_err == SVN_ERR_FS_REP_SHARING_NOT_ALLOWED)
+ {
+ svn_error_clear(err);
+ SVN_ERR(svn_cmdline_printf(pool,
+ _("svnadmin: Warning - this repository has rep-sharing disabled."
+ " Building rep-cache has no effect.\n")));
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ return err;
+ }
+}
+
+/* This implements `svn_opt_subcommand_t'. */
+static svn_error_t *
+subcommand_build_repcache(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ struct svnadmin_opt_state *opt_state = baton;
+ svn_repos_t *repos;
+ svn_fs_t *fs;
+ svn_revnum_t youngest;
+ svn_revnum_t lower;
+ svn_revnum_t upper;
+
+ /* Expect no more arguments. */
+ SVN_ERR(parse_args(NULL, os, 0, 0, pool));
+
+ SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool));
+ fs = svn_repos_fs(repos);
+ SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
+
+ SVN_ERR(get_revnum(&lower, &opt_state->start_revision,
+ youngest, repos, pool));
+ SVN_ERR(get_revnum(&upper, &opt_state->end_revision,
+ youngest, repos, pool));
+
+ if (SVN_IS_VALID_REVNUM(lower) && SVN_IS_VALID_REVNUM(upper))
+ {
+ if (lower > upper)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("First revision cannot be higher than second"));
+ }
+ else if (SVN_IS_VALID_REVNUM(lower))
+ {
+ upper = lower;
+ }
+ else
+ {
+ upper = youngest;
+ }
+
+ SVN_ERR(build_rep_cache(fs, lower, upper, opt_state, pool));
+
+ return SVN_NO_ERROR;
+}
+
/** Main. **/
@@ -2794,7 +3049,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
svn_error_t *err;
apr_status_t apr_err;
- const svn_opt_subcommand_desc2_t *subcommand = NULL;
+ const svn_opt_subcommand_desc3_t *subcommand = NULL;
struct svnadmin_opt_state opt_state = { 0 };
apr_getopt_t *os;
int opt_id;
@@ -3049,7 +3304,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
just typos/mistakes. Whatever the case, the subcommand to
actually run is subcommand_help(). */
if (opt_state.help)
- subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help");
+ subcommand = svn_opt_get_canonical_subcommand3(cmd_table, "help");
/* If we're not running the `help' subcommand, then look for a
subcommand in the first argument. */
@@ -3060,8 +3315,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
if (opt_state.version)
{
/* Use the "help" subcommand to handle the "--version" option. */
- static const svn_opt_subcommand_desc2_t pseudo_cmd =
- { "--version", subcommand_help, {0}, "",
+ static const svn_opt_subcommand_desc3_t pseudo_cmd =
+ { "--version", subcommand_help, {0}, {""},
{svnadmin__version, /* must accept its own option */
'q', /* --quiet */
} };
@@ -3083,7 +3338,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++],
pool));
- subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg);
+ subcommand = svn_opt_get_canonical_subcommand3(cmd_table, first_arg);
if (subcommand == NULL)
{
svn_error_clear(
@@ -3135,11 +3390,11 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
if (opt_id == 'h' || opt_id == '?')
continue;
- if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL))
+ if (! svn_opt_subcommand_takes_option4(subcommand, opt_id, NULL))
{
const char *optstr;
const apr_getopt_option_t *badopt =
- svn_opt_get_option_from_code2(opt_id, options_table, subcommand,
+ svn_opt_get_option_from_code3(opt_id, options_table, subcommand,
pool);
svn_opt_format_option(&optstr, badopt, FALSE, pool);
if (subcommand->name[0] == '-')