📄 main.c
字号:
/* Baton for initializing the destination repository while locked. */typedef struct { const char *from_url; const char *to_url; apr_hash_t *config; svn_ra_callbacks2_t *callbacks;} init_baton_t;/* Initialize the repository associated with RA session TO_SESSION, * using information found in baton B, while the repository is * locked. Implements `with_locked_func_t' interface. */static svn_error_t *do_initialize(svn_ra_session_t *to_session, void *b, apr_pool_t *pool){ svn_ra_session_t *from_session; init_baton_t *baton = b; svn_string_t *from_url; svn_revnum_t latest; const char *uuid; /* First, sanity check to see that we're copying into a brand new repos. */ SVN_ERR(svn_ra_get_latest_revnum(to_session, &latest, pool)); if (latest != 0) return svn_error_create (APR_EINVAL, NULL, _("Cannot initialize a repository with content in it")); /* And check to see if anyone's run initialize on it before... We may want a --force option to override this check. */ SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL, &from_url, pool)); if (from_url) return svn_error_createf (APR_EINVAL, NULL, _("Destination repository is already synchronizing from '%s'"), from_url->data); /* Now fill in our bookkeeping info in the dest repository. */ SVN_ERR(svn_ra_open2(&from_session, baton->from_url, baton->callbacks, baton, baton->config, pool)); SVN_ERR(check_if_session_is_at_repos_root(from_session, baton->from_url, pool)); SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL, svn_string_create(baton->from_url, pool), pool)); SVN_ERR(svn_ra_get_uuid(from_session, &uuid, pool)); SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_UUID, svn_string_create(uuid, pool), pool)); SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_LAST_MERGED_REV, svn_string_create("0", pool), pool)); /* Finally, copy all non-svnsync revprops from rev 0 of the source repos into the dest repos. */ SVN_ERR(copy_revprops(from_session, to_session, 0, FALSE, pool)); /* TODO: It would be nice if we could set the dest repos UUID to be equal to the UUID of the source repos, at least optionally. That way people could check out/log/diff using a local fast mirror, but switch --relocate to the actual final repository in order to make changes... But at this time, the RA layer doesn't have a way to set a UUID. */ return SVN_NO_ERROR;}/* SUBCOMMAND: init */static svn_error_t *initialize_cmd(apr_getopt_t *os, void *b, apr_pool_t *pool){ svn_ra_callbacks2_t callbacks = { 0 }; const char *to_url, *from_url; svn_ra_session_t *to_session; opt_baton_t *opt_baton = b; apr_array_header_t *args; init_baton_t baton; SVN_ERR(svn_opt_parse_num_args(&args, os, 2, pool)); to_url = svn_path_canonicalize(APR_ARRAY_IDX(args, 0, const char *), pool); from_url = svn_path_canonicalize(APR_ARRAY_IDX(args, 1, const char *), pool); if (! svn_path_is_url(to_url)) return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Path '%s' is not a URL"), to_url); if (! svn_path_is_url(from_url)) return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Path '%s' is not a URL"), from_url); baton.to_url = svn_path_canonicalize(to_url, pool); baton.from_url = svn_path_canonicalize(from_url, pool); baton.config = opt_baton->config; callbacks.open_tmp_file = open_tmp_file; callbacks.auth_baton = opt_baton->auth_baton; baton.callbacks = &callbacks; SVN_ERR(svn_ra_open2(&to_session, baton.to_url, &callbacks, &baton, baton.config, pool)); SVN_ERR(check_if_session_is_at_repos_root(to_session, baton.to_url, pool)); SVN_ERR(with_locked(to_session, do_initialize, &baton, pool)); return SVN_NO_ERROR;}/*** Syncronization Editor ***//* This editor has a couple of jobs. * * First, it needs to filter out the propchanges that can't be passed over * libsvn_ra. * * Second, it needs to adjust for the fact that we might not actually have * permission to see all of the data from the remote repository, which means * we could get revisions that are totally empty from our point of view. * * Third, it needs to adjust copyfrom paths, adding the root url for the * destination repository to the beginning of them. *//* Edit baton */typedef struct { const svn_delta_editor_t *wrapped_editor; void *wrapped_edit_baton; const char *to_url; /* URL we're copying into, for correct copyfrom URLs */ svn_boolean_t called_open_root; svn_revnum_t base_revision;} edit_baton_t;/* A dual-purpose baton for files and directories. */typedef struct { void *edit_baton; void *wrapped_node_baton;} node_baton_t;/*** Editor vtable functions ***/static svn_error_t *set_target_revision(void *edit_baton, svn_revnum_t target_revision, apr_pool_t *pool){ edit_baton_t *eb = edit_baton; return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, target_revision, pool);}static svn_error_t *open_root(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *pool, void **root_baton){ edit_baton_t *eb = edit_baton; node_baton_t *dir_baton = apr_palloc(pool, sizeof(*dir_baton)); SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton, base_revision, pool, &dir_baton->wrapped_node_baton)); eb->called_open_root = TRUE; dir_baton->edit_baton = edit_baton; *root_baton = dir_baton; return SVN_NO_ERROR;}static svn_error_t *delete_entry(const char *path, svn_revnum_t base_revision, void *parent_baton, apr_pool_t *pool){ node_baton_t *pb = parent_baton; edit_baton_t *eb = pb->edit_baton; return eb->wrapped_editor->delete_entry(path, base_revision, pb->wrapped_node_baton, pool);}static svn_error_t *add_directory(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_rev, apr_pool_t *pool, void **child_baton){ node_baton_t *pb = parent_baton; edit_baton_t *eb = pb->edit_baton; node_baton_t *b = apr_palloc(pool, sizeof(*b)); if (copyfrom_path) copyfrom_path = apr_psprintf(pool, "%s%s", eb->to_url, svn_path_uri_encode(copyfrom_path, pool)); SVN_ERR(eb->wrapped_editor->add_directory(path, pb->wrapped_node_baton, copyfrom_path, copyfrom_rev, pool, &b->wrapped_node_baton)); b->edit_baton = eb; *child_baton = b; return SVN_NO_ERROR;}static svn_error_t *open_directory(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *pool, void **child_baton){ node_baton_t *pb = parent_baton; edit_baton_t *eb = pb->edit_baton; node_baton_t *db = apr_palloc(pool, sizeof(*db)); SVN_ERR(eb->wrapped_editor->open_directory(path, pb->wrapped_node_baton, base_revision, pool, &db->wrapped_node_baton)); db->edit_baton = eb; *child_baton = db; return SVN_NO_ERROR;}static svn_error_t *add_file(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_rev, apr_pool_t *pool, void **file_baton){ node_baton_t *pb = parent_baton; edit_baton_t *eb = pb->edit_baton; node_baton_t *fb = apr_palloc(pool, sizeof(*fb)); if (copyfrom_path) copyfrom_path = apr_psprintf(pool, "%s%s", eb->to_url, svn_path_uri_encode(copyfrom_path, pool)); SVN_ERR(eb->wrapped_editor->add_file(path, pb->wrapped_node_baton, copyfrom_path, copyfrom_rev, pool, &fb->wrapped_node_baton)); fb->edit_baton = eb; *file_baton = fb; return SVN_NO_ERROR;}static svn_error_t *open_file(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *pool, void **file_baton){ node_baton_t *pb = parent_baton; edit_baton_t *eb = pb->edit_baton; node_baton_t *fb = apr_palloc(pool, sizeof(*fb)); SVN_ERR(eb->wrapped_editor->open_file(path, pb->wrapped_node_baton, base_revision, pool, &fb->wrapped_node_baton)); fb->edit_baton = eb; *file_baton = fb; return SVN_NO_ERROR;}static svn_error_t *apply_textdelta(void *file_baton, const char *base_checksum, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **handler_baton){ node_baton_t *fb = file_baton; edit_baton_t *eb = fb->edit_baton; return eb->wrapped_editor->apply_textdelta(fb->wrapped_node_baton, base_checksum, pool, handler, handler_baton);}static svn_error_t *close_file(void *file_baton, const char *text_checksum, apr_pool_t *pool){ node_baton_t *fb = file_baton; edit_baton_t *eb = fb->edit_baton; return eb->wrapped_editor->close_file(fb->wrapped_node_baton, text_checksum, pool);}static svn_error_t *absent_file(const char *path, void *file_baton, apr_pool_t *pool){ node_baton_t *fb = file_baton; edit_baton_t *eb = fb->edit_baton; return eb->wrapped_editor->absent_file(path, fb->wrapped_node_baton, pool);}static svn_error_t *close_directory(void *dir_baton, apr_pool_t *pool){ node_baton_t *db = dir_baton; edit_baton_t *eb = db->edit_baton; return eb->wrapped_editor->close_directory(db->wrapped_node_baton, pool);}static svn_error_t *absent_directory(const char *path, void *dir_baton, apr_pool_t *pool){ node_baton_t *db = dir_baton; edit_baton_t *eb = db->edit_baton; return eb->wrapped_editor->absent_directory(path, db->wrapped_node_baton, pool);}static svn_error_t *change_file_prop(void *file_baton, const char *name, const svn_string_t *value, apr_pool_t *pool){ node_baton_t *fb = file_baton; edit_baton_t *eb = fb->edit_baton; /* only regular properties can pass over libsvn_ra */ if (svn_property_kind(NULL, name) != svn_prop_regular_kind) return SVN_NO_ERROR; return eb->wrapped_editor->change_file_prop(fb->wrapped_node_baton, name, value, pool);}static svn_error_t *change_dir_prop(void *dir_baton, const char *name, const svn_string_t *value, apr_pool_t *pool){ node_baton_t *db = dir_baton; edit_baton_t *eb = db->edit_baton; /* only regular properties can pass over libsvn_ra */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -