📄 load.c
字号:
if ((src_rev_from_map = apr_hash_get (pb->rev_map, &nb->copyfrom_rev,
sizeof(nb->copyfrom_rev))))
src_rev = *src_rev_from_map;
if (! SVN_IS_VALID_REVNUM(src_rev))
return svn_error_createf (SVN_ERR_FS_NO_SUCH_REVISION, NULL,
_("Relative source revision %ld is not"
" available in current repository"),
src_rev);
SVN_ERR (svn_fs_revision_root (©_root, pb->fs, src_rev, pool));
SVN_ERR (svn_fs_copy (copy_root, nb->copyfrom_path,
rb->txn_root, nb->path, pool));
if (pb->outstream)
{
apr_size_t len = 9;
SVN_ERR (svn_stream_write (pb->outstream, "COPIED...", &len));
}
}
return SVN_NO_ERROR;
}
static svn_error_t *
uuid_record (const char *uuid,
void *parse_baton,
apr_pool_t *pool)
{
struct parse_baton *pb = parse_baton;
svn_revnum_t youngest_rev;
if (pb->uuid_action == svn_repos_load_uuid_ignore)
return SVN_NO_ERROR;
if (pb->uuid_action != svn_repos_load_uuid_force)
{
SVN_ERR (svn_fs_youngest_rev (&youngest_rev, pb->fs, pool));
if (youngest_rev != 0)
return SVN_NO_ERROR;
}
return svn_fs_set_uuid (pb->fs, uuid, pool);
}
static svn_error_t *
new_node_record (void **node_baton,
apr_hash_t *headers,
void *revision_baton,
apr_pool_t *pool)
{
struct revision_baton *rb = revision_baton;
struct parse_baton *pb = rb->pb;
struct node_baton *nb;
if (rb->rev == 0)
return svn_error_create (SVN_ERR_STREAM_MALFORMED_DATA, NULL,
"Malformed dumpstream: "
"Revision 0 must not contain node records");
nb = make_node_baton (headers, rb, pool);
switch (nb->action)
{
case svn_node_action_change:
{
if (pb->outstream)
SVN_ERR (svn_stream_printf (pb->outstream, pool,
" * editing path : %s ...",
nb->path));
break;
}
case svn_node_action_delete:
{
if (pb->outstream)
SVN_ERR (svn_stream_printf (pb->outstream, pool,
" * deleting path : %s ...",
nb->path));
SVN_ERR (svn_fs_delete (rb->txn_root, nb->path, pool));
break;
}
case svn_node_action_add:
{
if (pb->outstream)
SVN_ERR (svn_stream_printf (pb->outstream, pool,
" * adding path : %s ...",
nb->path));
SVN_ERR (maybe_add_with_history (nb, rb, pool));
break;
}
case svn_node_action_replace:
{
if (pb->outstream)
SVN_ERR (svn_stream_printf (pb->outstream, pool,
" * replacing path : %s ...",
nb->path));
SVN_ERR (svn_fs_delete (rb->txn_root, nb->path, pool));
SVN_ERR (maybe_add_with_history (nb, rb, pool));
break;
}
default:
return svn_error_createf (SVN_ERR_STREAM_UNRECOGNIZED_DATA, NULL,
"Unrecognized node-action on node '%s'",
nb->path);
}
*node_baton = nb;
return SVN_NO_ERROR;
}
static svn_error_t *
set_revision_property (void *baton,
const char *name,
const svn_string_t *value)
{
struct revision_baton *rb = baton;
if (rb->rev > 0)
{
SVN_ERR (svn_fs_change_txn_prop (rb->txn, name, value, rb->pool));
/* Remember any datestamp that passes through! (See comment in
close_revision() below.) */
if (! strcmp (name, SVN_PROP_REVISION_DATE))
rb->datestamp = svn_string_dup (value, rb->pool);
}
else if (rb->rev == 0)
{
/* Special case: set revision 0 properties when loading into an
'empty' filesystem. */
struct parse_baton *pb = rb->pb;
svn_revnum_t youngest_rev;
SVN_ERR (svn_fs_youngest_rev (&youngest_rev, pb->fs, rb->pool));
if (youngest_rev == 0)
SVN_ERR (svn_fs_change_rev_prop (pb->fs, 0, name, value, rb->pool));
}
return SVN_NO_ERROR;
}
static svn_error_t *
set_node_property (void *baton,
const char *name,
const svn_string_t *value)
{
struct node_baton *nb = baton;
struct revision_baton *rb = nb->rb;
SVN_ERR (svn_fs_change_node_prop (rb->txn_root, nb->path,
name, value, nb->pool));
return SVN_NO_ERROR;
}
static svn_error_t *
delete_node_property (void *baton,
const char *name)
{
struct node_baton *nb = baton;
struct revision_baton *rb = nb->rb;
SVN_ERR (svn_fs_change_node_prop (rb->txn_root, nb->path,
name, NULL, nb->pool));
return SVN_NO_ERROR;
}
static svn_error_t *
remove_node_props (void *baton)
{
struct node_baton *nb = baton;
struct revision_baton *rb = nb->rb;
apr_hash_t *proplist;
apr_hash_index_t *hi;
SVN_ERR (svn_fs_node_proplist (&proplist,
rb->txn_root, nb->path, nb->pool));
for (hi = apr_hash_first (nb->pool, proplist); hi; hi = apr_hash_next (hi))
{
const void *key;
apr_ssize_t keylen;
void *val;
apr_hash_this (hi, &key, &keylen, &val);
SVN_ERR (svn_fs_change_node_prop (rb->txn_root, nb->path,
(const char *) key, NULL,
nb->pool));
}
return SVN_NO_ERROR;
}
static svn_error_t *
apply_textdelta (svn_txdelta_window_handler_t *handler,
void **handler_baton,
void *node_baton)
{
struct node_baton *nb = node_baton;
struct revision_baton *rb = nb->rb;
return svn_fs_apply_textdelta (handler, handler_baton,
rb->txn_root, nb->path,
NULL, nb->md5_checksum,
nb->pool);
}
static svn_error_t *
set_fulltext (svn_stream_t **stream,
void *node_baton)
{
struct node_baton *nb = node_baton;
struct revision_baton *rb = nb->rb;
return svn_fs_apply_text (stream,
rb->txn_root, nb->path,
nb->md5_checksum,
nb->pool);
}
static svn_error_t *
close_node (void *baton)
{
struct node_baton *nb = baton;
struct revision_baton *rb = nb->rb;
struct parse_baton *pb = rb->pb;
if (pb->outstream)
{
apr_size_t len = 7;
SVN_ERR (svn_stream_write (pb->outstream, " done.\n", &len));
}
return SVN_NO_ERROR;
}
static svn_error_t *
close_revision (void *baton)
{
struct revision_baton *rb = baton;
struct parse_baton *pb = rb->pb;
const char *conflict_msg = NULL;
svn_revnum_t *old_rev, *new_rev;
svn_error_t *err;
if (rb->rev <= 0)
return SVN_NO_ERROR;
/* Prepare memory for saving dump-rev -> in-repos-rev mapping. */
old_rev = apr_palloc (pb->pool, sizeof(svn_revnum_t) * 2);
new_rev = old_rev + 1;
*old_rev = rb->rev;
err = svn_fs_commit_txn (&conflict_msg, &(*new_rev), rb->txn, rb->pool);
if (err)
{
svn_error_clear (svn_fs_abort_txn (rb->txn, rb->pool));
if (conflict_msg)
return svn_error_quick_wrap (err, conflict_msg);
else
return err;
}
/* After a successful commit, must record the dump-rev -> in-repos-rev
mapping, so that copyfrom instructions in the dump file can look up the
correct repository revision to copy from. */
apr_hash_set (pb->rev_map, old_rev, sizeof(svn_revnum_t), new_rev);
/* Deltify the predecessors of paths changed in this revision. */
SVN_ERR (svn_fs_deltify_revision (pb->fs, *new_rev, rb->pool));
/* Grrr, svn_fs_commit_txn rewrites the datestamp property to the
current clock-time. We don't want that, we want to preserve
history exactly. Good thing revision props aren't versioned! */
if (rb->datestamp)
SVN_ERR (svn_fs_change_rev_prop (pb->fs, *new_rev,
SVN_PROP_REVISION_DATE, rb->datestamp,
rb->pool));
if (pb->outstream)
{
if (*new_rev == rb->rev)
{
SVN_ERR (svn_stream_printf (pb->outstream, rb->pool,
_("\n------- Committed revision %ld"
" >>>\n\n"), *new_rev));
}
else
{
SVN_ERR (svn_stream_printf (pb->outstream, rb->pool,
_("\n------- Committed new rev %ld"
" (loaded from original rev %ld"
") >>>\n\n"), *new_rev, rb->rev));
}
}
return SVN_NO_ERROR;
}
/*----------------------------------------------------------------------*/
/** The public routines **/
svn_error_t *
svn_repos_get_fs_build_parser2 (const svn_repos_parser_fns2_t **callbacks,
void **parse_baton,
svn_repos_t *repos,
svn_boolean_t use_history,
enum svn_repos_load_uuid uuid_action,
svn_stream_t *outstream,
const char *parent_dir,
apr_pool_t *pool)
{
const svn_repos_parser_fns_t *fns;
svn_repos_parser_fns2_t *parser;
/* Fetch the old-style vtable and baton, convert the vtable to a
* new-style vtable, and set the new callbacks. */
SVN_ERR (svn_repos_get_fs_build_parser (&fns, parse_baton, repos,
use_history, uuid_action, outstream,
parent_dir, pool));
parser = fns2_from_fns (fns, pool);
parser->delete_node_property = delete_node_property;
parser->apply_textdelta = apply_textdelta;
*callbacks = parser;
return SVN_NO_ERROR;
}
svn_error_t *
svn_repos_get_fs_build_parser (const svn_repos_parser_fns_t **parser_callbacks,
void **parse_baton,
svn_repos_t *repos,
svn_boolean_t use_history,
enum svn_repos_load_uuid uuid_action,
svn_stream_t *outstream,
const char *parent_dir,
apr_pool_t *pool)
{
svn_repos_parser_fns_t *parser = apr_pcalloc (pool, sizeof(*parser));
struct parse_baton *pb = apr_pcalloc (pool, sizeof(*pb));
parser->new_revision_record = new_revision_record;
parser->new_node_record = new_node_record;
parser->uuid_record = uuid_record;
parser->set_revision_property = set_revision_property;
parser->set_node_property = set_node_property;
parser->remove_node_props = remove_node_props;
parser->set_fulltext = set_fulltext;
parser->close_node = close_node;
parser->close_revision = close_revision;
pb->repos = repos;
pb->fs = svn_repos_fs (repos);
pb->use_history = use_history;
pb->outstream = outstream;
pb->uuid_action = uuid_action;
pb->parent_dir = parent_dir;
pb->pool = pool;
pb->rev_map = apr_hash_make (pool);
*parser_callbacks = parser;
*parse_baton = pb;
return SVN_NO_ERROR;
}
svn_error_t *
svn_repos_load_fs (svn_repos_t *repos,
svn_stream_t *dumpstream,
svn_stream_t *feedback_stream,
enum svn_repos_load_uuid uuid_action,
const char *parent_dir,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
{
const svn_repos_parser_fns2_t *parser;
void *parse_baton;
/* This is really simple. */
SVN_ERR (svn_repos_get_fs_build_parser2 (&parser, &parse_baton,
repos,
TRUE, /* look for copyfrom revs */
uuid_action,
feedback_stream,
parent_dir,
pool));
SVN_ERR (svn_repos_parse_dumpstream2 (dumpstream, parser, parse_baton,
cancel_func, cancel_baton, pool));
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -