📄 main.c
字号:
*revnum = SVN_INVALID_REVNUM;
else
return svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, "Invalid revision specifier");
if (*revnum > youngest)
return svn_error_createf
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
"Revisions must not be greater than the youngest revision (%"
SVN_REVNUM_T_FMT ")", youngest);
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_create (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
struct svnadmin_opt_state *opt_state = baton;
svn_repos_t *repos;
apr_hash_t *config;
apr_hash_t *fs_config = apr_hash_make (pool);;
apr_hash_set (fs_config, SVN_FS_CONFIG_BDB_TXN_NOSYNC,
APR_HASH_KEY_STRING,
(opt_state->bdb_txn_nosync ? "1" : "0"));
apr_hash_set (fs_config, SVN_FS_CONFIG_BDB_LOG_AUTOREMOVE,
APR_HASH_KEY_STRING,
(opt_state->bdb_log_keep ? "0" : "1"));
if (opt_state->fs_type)
apr_hash_set (fs_config, SVN_FS_CONFIG_FS_TYPE,
APR_HASH_KEY_STRING,
opt_state->fs_type);
SVN_ERR (svn_config_get_config (&config, opt_state->config_dir, pool));
SVN_ERR (svn_repos_create (&repos, opt_state->repository_path,
NULL, NULL,
config, fs_config, pool));
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_deltify (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 start = SVN_INVALID_REVNUM, end = SVN_INVALID_REVNUM;
svn_revnum_t youngest, revision;
apr_pool_t *subpool = svn_pool_create (pool);
SVN_ERR (open_repos (&repos, opt_state->repository_path, pool));
fs = svn_repos_fs (repos);
SVN_ERR (svn_fs_youngest_rev (&youngest, fs, pool));
/* Find the revision numbers at which to start and end. */
SVN_ERR (get_revnum (&start, &opt_state->start_revision,
youngest, repos, pool));
SVN_ERR (get_revnum (&end, &opt_state->end_revision,
youngest, repos, pool));
/* Fill in implied revisions if necessary. */
if (start == SVN_INVALID_REVNUM)
start = youngest;
if (end == SVN_INVALID_REVNUM)
end = start;
if (start > end)
return svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("First revision cannot be higher than second"));
/* Loop over the requested revision range, performing the
predecessor deltification on paths changed in each. */
for (revision = start; revision <= end; revision++)
{
svn_pool_clear (subpool);
SVN_ERR (check_cancel (NULL));
if (! opt_state->quiet)
SVN_ERR (svn_cmdline_printf (subpool, _("Deltifying revision %ld..."),
revision));
SVN_ERR (svn_fs_deltify_revision (fs, revision, subpool));
if (! opt_state->quiet)
SVN_ERR (svn_cmdline_printf (subpool, _("done.\n")));
}
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_dump (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_stream_t *stdout_stream, *stderr_stream = NULL;
svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM;
svn_revnum_t youngest;
SVN_ERR (open_repos (&repos, opt_state->repository_path, pool));
fs = svn_repos_fs (repos);
SVN_ERR (svn_fs_youngest_rev (&youngest, fs, pool));
/* Find the revision numbers at which to start and end. */
SVN_ERR (get_revnum (&lower, &opt_state->start_revision,
youngest, repos, pool));
SVN_ERR (get_revnum (&upper, &opt_state->end_revision,
youngest, repos, pool));
/* Fill in implied revisions if necessary. */
if (lower == SVN_INVALID_REVNUM)
{
lower = 0;
upper = youngest;
}
else if (upper == SVN_INVALID_REVNUM)
{
upper = lower;
}
if (lower > upper)
return svn_error_create
(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("First revision cannot be higher than second"));
/* Run the dump to STDOUT. Let the user redirect output into
a file if they want. :-) */
SVN_ERR (create_stdio_stream (&stdout_stream, apr_file_open_stdout, pool));
/* Progress feedback goes to stderr, unless they asked to suppress
it. */
if (! opt_state->quiet)
SVN_ERR (create_stdio_stream (&stderr_stream,
apr_file_open_stderr, pool));
SVN_ERR (svn_repos_dump_fs2 (repos, stdout_stream, stderr_stream,
lower, upper, opt_state->incremental,
opt_state->use_deltas, check_cancel, NULL,
pool));
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_help (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
struct svnadmin_opt_state *opt_state = baton;
const char *header =
_("general usage: svnadmin SUBCOMMAND REPOS_PATH [ARGS & OPTIONS ...]\n"
"Type \"svnadmin help <subcommand>\" for help on a specific"
" subcommand.\n"
"\n"
"Available subcommands:\n");
SVN_ERR (svn_opt_print_help (os, "svnadmin",
opt_state ? opt_state->version : FALSE,
FALSE, NULL,
header, cmd_table, options_table, NULL,
pool));
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_load (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
struct svnadmin_opt_state *opt_state = baton;
svn_repos_t *repos;
svn_stream_t *stdin_stream, *stdout_stream = NULL;
SVN_ERR (open_repos (&repos, opt_state->repository_path, pool));
/* Read the stream from STDIN. Users can redirect a file. */
SVN_ERR (create_stdio_stream (&stdin_stream,
apr_file_open_stdin, pool));
/* Have the parser dump feedback to STDOUT. */
if (! opt_state->quiet)
SVN_ERR (create_stdio_stream (&stdout_stream,
apr_file_open_stdout, pool));
SVN_ERR (svn_repos_load_fs (repos, stdin_stream, stdout_stream,
opt_state->uuid_action, opt_state->parent_dir,
check_cancel, NULL, pool));
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_lstxns (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;
apr_array_header_t *txns;
int i;
SVN_ERR (open_repos (&repos, opt_state->repository_path, pool));
fs = svn_repos_fs (repos);
SVN_ERR (svn_fs_list_transactions (&txns, fs, pool));
/* Loop, printing revisions. */
for (i = 0; i < txns->nelts; i++)
{
SVN_ERR (svn_cmdline_printf (pool, "%s\n",
APR_ARRAY_IDX (txns, i, const char *)));
}
return SVN_NO_ERROR;
}
/* A callback which is called when the recovery starts. */
static svn_error_t *
recovery_started (void *baton)
{
apr_pool_t *pool = (apr_pool_t *)baton;
SVN_ERR (svn_cmdline_printf (pool,
_("Repository lock acquired.\n"
"Please wait; recovering the"
" repository may take some time...\n")));
SVN_ERR (svn_cmdline_fflush (stdout));
/* Enable cancellation signal handlers. */
setup_cancellation_signals (signal_handler);
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_recover (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
svn_revnum_t youngest_rev;
svn_repos_t *repos;
svn_error_t *err;
struct svnadmin_opt_state *opt_state = baton;
/* Restore default signal handlers until after we have acquired the
* exclusive lock so that the user interrupt before we actually
* touch the repository. */
setup_cancellation_signals (SIG_DFL);
err = svn_repos_recover2 (opt_state->repository_path, TRUE,
recovery_started, pool, pool);
if (err)
{
if (! APR_STATUS_IS_EAGAIN (err->apr_err))
return err;
svn_error_clear (err);
if (! opt_state->wait)
return svn_error_create (SVN_ERR_REPOS_LOCKED, NULL,
_("Failed to get exclusive repository "
"access; perhaps another process\n"
"such as httpd, svnserve or svn "
"has it open?"));
SVN_ERR (svn_cmdline_printf (pool,
_("Waiting on repository lock; perhaps"
" another process has it open?\n")));
SVN_ERR (svn_cmdline_fflush (stdout));
SVN_ERR (svn_repos_recover2 (opt_state->repository_path, FALSE,
recovery_started, pool, pool));
}
SVN_ERR (svn_cmdline_printf (pool, _("\nRecovery completed.\n")));
/* Since db transactions may have been replayed, it's nice to tell
people what the latest revision is. It also proves that the
recovery actually worked. */
SVN_ERR (open_repos (&repos, opt_state->repository_path, pool));
SVN_ERR (svn_fs_youngest_rev (&youngest_rev, svn_repos_fs (repos), pool));
SVN_ERR (svn_cmdline_printf (pool, _("The latest repos revision is %ld.\n"),
youngest_rev));
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
list_dblogs (apr_getopt_t *os, void *baton, svn_boolean_t only_unused,
apr_pool_t *pool)
{
struct svnadmin_opt_state *opt_state = baton;
apr_array_header_t *logfiles;
int i;
SVN_ERR (svn_repos_db_logfiles (&logfiles,
opt_state->repository_path,
only_unused,
pool));
/* Loop, printing log files. We append the log paths to the
repository path, making sure to return everything to the native
style before printing. */
for (i = 0; i < logfiles->nelts; i++)
{
const char *log_utf8;
log_utf8 = svn_path_join (opt_state->repository_path,
APR_ARRAY_IDX (logfiles, i, const char *),
pool);
log_utf8 = svn_path_local_style (log_utf8, pool);
SVN_ERR (svn_cmdline_printf (pool, "%s\n", log_utf8));
}
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_list_dblogs (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
SVN_ERR (list_dblogs (os, baton, FALSE, pool));
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_list_unused_dblogs (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
SVN_ERR (list_dblogs (os, baton, TRUE, pool));
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_rmtxns (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_fs_txn_t *txn;
apr_array_header_t *args;
int i;
apr_pool_t *subpool = svn_pool_create (pool);
SVN_ERR (open_repos (&repos, opt_state->repository_path, pool));
fs = svn_repos_fs (repos);
SVN_ERR (svn_opt_parse_all_args (&args, os, pool));
/* All the rest of the arguments are transaction names. */
for (i = 0; i < args->nelts; i++)
{
const char *txn_name = APR_ARRAY_IDX (args, i, const char *);
const char *txn_name_utf8;
svn_error_t *err;
SVN_ERR (svn_utf_cstring_to_utf8 (&txn_name_utf8, txn_name, subpool));
/* Try to open the txn. If that succeeds, try to abort it. */
err = svn_fs_open_txn (&txn, fs, txn_name_utf8, subpool);
if (! err)
err = svn_fs_abort_txn (txn, subpool);
/* If either the open or the abort of the txn fails because that
transaction is dead, just try to purge the thing. Else,
there was either an error worth reporting, or not error at
all. */
if (err && (err->apr_err == SVN_ERR_FS_TRANSACTION_DEAD))
{
svn_error_clear (err);
err = svn_fs_purge_txn (fs, txn_name_utf8, subpool);
}
/* If we had a real from the txn open, abort, or purge, we clear
that error and just report to the user that we had an issue
with this particular txn. */
if (err)
{
svn_handle_error (err, stderr, FALSE /* non-fatal */);
svn_error_clear (err);
}
else if (! opt_state->quiet)
{
SVN_ERR
(svn_cmdline_printf (subpool, _("Transaction '%s' removed.\n"),
txn_name));
}
svn_pool_clear (subpool);
}
return SVN_NO_ERROR;
}
/* This implements `svn_opt_subcommand_t'. */
static svn_error_t *
subcommand_setlog (apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
struct svnadmin_opt_state *opt_state = baton;
svn_repos_t *repos;
svn_stringbuf_t *file_contents;
const char *filename_utf8;
apr_array_header_t *args;
svn_string_t *log_contents = svn_string_create ("", pool);
if (opt_state->start_revision.kind != svn_opt_revision_number)
return svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -