📄 load.c
字号:
else { /* Hunt down the source revision in this fs. */ svn_fs_root_t *copy_root; svn_revnum_t src_rev = nb->copyfrom_rev - rb->rev_offset; svn_revnum_t *src_rev_from_map; 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)); 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: { SVN_ERR(svn_stream_printf(pb->outstream, pool, _(" * editing path : %s ..."), nb->path)); break; } case svn_node_action_delete: { 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: { 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: { 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; 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; /* Run the pre-commit hook, if so commanded. */ if (pb->use_pre_commit_hook) { const char *txn_name; err = svn_fs_txn_name(&txn_name, rb->txn, rb->pool); if (! err) err = svn_repos__hooks_pre_commit(pb->repos, txn_name, rb->pool); if (err) { svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool)); return err; } } /* Commit. */ if ((err = svn_fs_commit_txn(&conflict_msg, new_rev, rb->txn, rb->pool))) { 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; } /* Run post-commit hook, if so commanded. */ if (pb->use_post_commit_hook) { if ((err = svn_repos__hooks_post_commit(pb->repos, *new_rev, rb->pool))) return svn_error_create (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err, _("Commit succeeded, but post-commit hook failed")); } /* 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 (*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_parse_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_parse_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 ? outstream : svn_stream_empty(pool); 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_fs2(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_boolean_t use_pre_commit_hook, svn_boolean_t use_post_commit_hook, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool){ const svn_repos_parse_fns2_t *parser; void *parse_baton; struct parse_baton *pb; /* 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)); /* Heh. We know this is a parse_baton. This file made it. So cast away, and set our hook booleans. */ pb = parse_baton; pb->use_pre_commit_hook = use_pre_commit_hook; pb->use_post_commit_hook = use_post_commit_hook; SVN_ERR(svn_repos_parse_dumpstream2(dumpstream, parser, parse_baton, cancel_func, cancel_baton, pool)); 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){ return svn_repos_load_fs2(repos, dumpstream, feedback_stream, uuid_action, parent_dir, FALSE, FALSE, cancel_func, cancel_baton, pool);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -