export.c
来自「linux subdivision ying gai ke yi le ba」· C语言 代码 · 共 869 行 · 第 1/2 页
C
869 行
apr_pool_t *pool,
void **root_baton)
{
struct edit_baton *eb = edit_baton;
struct dir_baton *db = apr_pcalloc (pool, sizeof (*db));
SVN_ERR (open_root_internal (eb->root_path, eb->force,
eb->notify_func, eb->notify_baton, pool));
/* Build our dir baton. */
db->path = eb->root_path;
db->edit_baton = eb;
*root_baton = db;
return SVN_NO_ERROR;
}
/* Ensure the directory exists, and send feedback. */
static svn_error_t *
add_directory (const char *path,
void *parent_baton,
const char *copyfrom_path,
svn_revnum_t copyfrom_revision,
apr_pool_t *pool,
void **baton)
{
struct dir_baton *pb = parent_baton;
struct dir_baton *db = apr_pcalloc (pool, sizeof (*db));
struct edit_baton *eb = pb->edit_baton;
const char *full_path = svn_path_join (eb->root_path, path, pool);
svn_node_kind_t kind;
SVN_ERR (svn_io_check_path (full_path, &kind, pool));
if (kind == svn_node_none)
SVN_ERR (svn_io_dir_make (full_path, APR_OS_DEFAULT, pool));
else if (kind == svn_node_file)
return svn_error_createf (SVN_ERR_WC_NOT_DIRECTORY, NULL,
_("'%s' exists and is not a directory"),
full_path);
else if (! (kind == svn_node_dir && eb->force))
return svn_error_createf (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
_("'%s' already exists"), full_path);
if (eb->notify_func)
(*eb->notify_func) (eb->notify_baton,
full_path,
svn_wc_notify_update_add,
svn_node_dir,
NULL,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
/* Build our dir baton. */
db->path = full_path;
db->edit_baton = eb;
*baton = db;
return SVN_NO_ERROR;
}
/* Build a file baton. */
static svn_error_t *
add_file (const char *path,
void *parent_baton,
const char *copyfrom_path,
svn_revnum_t copyfrom_revision,
apr_pool_t *pool,
void **baton)
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
struct file_baton *fb = apr_pcalloc (pool, sizeof(*fb));
const char *full_path = svn_path_join (eb->root_path, path, pool);
const char *full_url = svn_path_join (eb->root_url, path, pool);
fb->edit_baton = eb;
fb->path = full_path;
fb->url = full_url;
fb->pool = pool;
*baton = fb;
return SVN_NO_ERROR;
}
static svn_error_t *
window_handler (svn_txdelta_window_t *window, void *baton)
{
struct handler_baton *hb = baton;
svn_error_t *err;
err = hb->apply_handler (window, hb->apply_baton);
if (err)
{
/* We failed to apply the patch; clean up the temporary file. */
apr_file_remove (hb->tmppath, hb->pool);
}
return err;
}
/* Write incoming data into the tmpfile stream */
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)
{
struct file_baton *fb = file_baton;
struct handler_baton *hb = apr_palloc (pool, sizeof (*hb));
SVN_ERR (svn_io_open_unique_file (&fb->tmp_file, &(fb->tmppath),
fb->path, ".tmp", FALSE, fb->pool));
hb->pool = pool;
hb->tmppath = fb->tmppath;
svn_txdelta_apply (svn_stream_empty (pool),
svn_stream_from_aprfile (fb->tmp_file, pool),
fb->text_digest, NULL, pool,
&hb->apply_handler, &hb->apply_baton);
*handler_baton = hb;
*handler = window_handler;
return SVN_NO_ERROR;
}
static svn_error_t *
change_file_prop (void *file_baton,
const char *name,
const svn_string_t *value,
apr_pool_t *pool)
{
struct file_baton *fb = file_baton;
if (! value)
return SVN_NO_ERROR;
/* Store only the magic three properties. */
if (strcmp (name, SVN_PROP_EOL_STYLE) == 0)
fb->eol_style_val = svn_string_dup (value, fb->pool);
else if (strcmp (name, SVN_PROP_KEYWORDS) == 0)
fb->keywords_val = svn_string_dup (value, fb->pool);
else if (strcmp (name, SVN_PROP_EXECUTABLE) == 0)
fb->executable_val = svn_string_dup (value, fb->pool);
/* Try to fill out the baton's keywords-structure too. */
else if (strcmp (name, SVN_PROP_ENTRY_COMMITTED_REV) == 0)
fb->revision = apr_pstrdup (fb->pool, value->data);
else if (strcmp (name, SVN_PROP_ENTRY_COMMITTED_DATE) == 0)
SVN_ERR (svn_time_from_cstring (&fb->date, value->data, fb->pool));
else if (strcmp (name, SVN_PROP_ENTRY_LAST_AUTHOR) == 0)
fb->author = apr_pstrdup (fb->pool, value->data);
else if (strcmp (name, SVN_PROP_SPECIAL) == 0)
fb->special = TRUE;
return SVN_NO_ERROR;
}
static svn_error_t *
change_dir_prop (void *dir_baton,
const char *name,
const svn_string_t *value,
apr_pool_t *pool)
{
struct dir_baton *db = dir_baton;
struct edit_baton *eb = db->edit_baton;
if (value && (strcmp (name, SVN_PROP_EXTERNALS) == 0))
add_externals (eb->externals, db->path, value);
return SVN_NO_ERROR;
}
/* Move the tmpfile to file, and send feedback. */
static svn_error_t *
close_file (void *file_baton,
const char *text_checksum,
apr_pool_t *pool)
{
struct file_baton *fb = file_baton;
struct edit_baton *eb = fb->edit_baton;
/* Was a txdelta even sent? */
if (! fb->tmppath)
return SVN_NO_ERROR;
SVN_ERR (svn_io_file_close (fb->tmp_file, fb->pool));
if (text_checksum)
{
const char *actual_checksum
= svn_md5_digest_to_cstring (fb->text_digest, pool);
if (actual_checksum && (strcmp (text_checksum, actual_checksum) != 0))
{
return svn_error_createf
(SVN_ERR_CHECKSUM_MISMATCH, NULL,
_("Checksum mismatch for '%s'; expected: '%s', actual: '%s'"),
fb->path, text_checksum, actual_checksum);
}
}
if ((! fb->eol_style_val) && (! fb->keywords_val) && (! fb->special))
{
SVN_ERR (svn_io_file_rename (fb->tmppath, fb->path, pool));
}
else
{
svn_subst_eol_style_t style;
const char *eol;
svn_subst_keywords_t final_kw = {0};
if (fb->eol_style_val)
SVN_ERR (get_eol_style (&style, &eol, fb->eol_style_val->data,
eb->native_eol));
if (fb->keywords_val)
SVN_ERR (svn_subst_build_keywords (&final_kw, fb->keywords_val->data,
fb->revision, fb->url, fb->date,
fb->author, pool));
SVN_ERR (svn_subst_copy_and_translate2
(fb->tmppath, fb->path,
fb->eol_style_val ? eol : NULL,
fb->eol_style_val ? TRUE : FALSE, /* repair */
fb->keywords_val ? &final_kw : NULL,
TRUE, /* expand */
fb->special,
pool));
SVN_ERR (svn_io_remove_file (fb->tmppath, pool));
}
if (fb->executable_val)
SVN_ERR (svn_io_set_file_executable (fb->path, TRUE, FALSE, pool));
if (fb->date && (! fb->special))
SVN_ERR (svn_io_set_file_affected_time (fb->date, fb->path, pool));
if (fb->edit_baton->notify_func)
(*fb->edit_baton->notify_func) (fb->edit_baton->notify_baton,
fb->path,
svn_wc_notify_update_add,
svn_node_file,
NULL,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
return SVN_NO_ERROR;
}
/*** Public Interfaces ***/
svn_error_t *
svn_client_export2 (svn_revnum_t *result_rev,
const char *from,
const char *to,
svn_opt_revision_t *revision,
svn_boolean_t force,
const char *native_eol,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_revnum_t edit_revision = SVN_INVALID_REVNUM;
svn_boolean_t use_ra = FALSE;
const char *URL;
if (! svn_path_is_url (from) &&
(revision->kind != svn_opt_revision_base) &&
(revision->kind != svn_opt_revision_committed) &&
(revision->kind != svn_opt_revision_working))
{
if (revision->kind == svn_opt_revision_unspecified)
{
/* Default to WORKING in the case that we have
been given a working copy path */
revision->kind = svn_opt_revision_working;
}
else
{
use_ra = TRUE;
SVN_ERR (svn_client_url_from_path (&URL, from, pool));
if (! URL)
return svn_error_createf (SVN_ERR_ENTRY_MISSING_URL, NULL,
_("'%s' has no URL"), from);
}
}
else
{
URL = svn_path_canonicalize (from, pool);
}
if (svn_path_is_url (from) || use_ra)
{
svn_revnum_t revnum;
void *ra_baton, *session;
svn_ra_plugin_t *ra_lib;
void *edit_baton;
svn_node_kind_t kind;
const svn_delta_editor_t *export_editor;
const svn_ra_reporter_t *reporter;
void *report_baton;
struct edit_baton *eb = apr_pcalloc (pool, sizeof (*eb));
svn_delta_editor_t *editor = svn_delta_default_editor (pool);
svn_boolean_t use_sleep = FALSE;
eb->root_path = to;
eb->root_url = URL;
eb->force = force;
eb->target_revision = &edit_revision;
eb->notify_func = ctx->notify_func;
eb->notify_baton = ctx->notify_baton;
eb->externals = apr_hash_make (pool);
eb->native_eol = native_eol;
editor->set_target_revision = set_target_revision;
editor->open_root = open_root;
editor->add_directory = add_directory;
editor->add_file = add_file;
editor->apply_textdelta = apply_textdelta;
editor->close_file = close_file;
editor->change_file_prop = change_file_prop;
editor->change_dir_prop = change_dir_prop;
SVN_ERR (svn_delta_get_cancellation_editor (ctx->cancel_func,
ctx->cancel_baton,
editor,
eb,
&export_editor,
&edit_baton,
pool));
SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
SVN_ERR (svn_ra_get_ra_library (&ra_lib, ra_baton, URL, pool));
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, URL, NULL,
NULL, NULL, FALSE, TRUE,
ctx, pool));
/* Unfortunately, it's not kosher to pass an invalid revnum into
set_path(), so we actually need to convert it to HEAD. */
if (revision->kind == svn_opt_revision_unspecified)
revision->kind = svn_opt_revision_head;
SVN_ERR (svn_client__get_revision_number
(&revnum, ra_lib, session, revision, from, pool));
/* Manufacture a basic 'report' to the update reporter. */
SVN_ERR (ra_lib->do_update (session,
&reporter, &report_baton,
revnum,
"", /* no sub-target */
TRUE, /* recurse */
export_editor, edit_baton, pool));
SVN_ERR (reporter->set_path (report_baton, "", revnum,
TRUE, /* "help, my dir is empty!" */
pool));
SVN_ERR (reporter->finish_report (report_baton, pool));
/* Special case: Due to our sly export/checkout method of
* updating an empty directory, no target will have been created
* if the exported item is itself an empty directory
* (export_editor->open_root never gets called, because there
* are no "changes" to make to the empty dir we reported to the
* repository).
*
* So we just create the empty dir manually; but we do it via
* open_root_internal(), in order to get proper notification.
*/
SVN_ERR (svn_io_check_path (to, &kind, pool));
if (kind == svn_node_none)
SVN_ERR (open_root_internal
(to, force, ctx->notify_func, ctx->notify_baton, pool));
SVN_ERR (svn_client__fetch_externals (eb->externals, TRUE,
&use_sleep, ctx, pool));
}
else
{
/* just copy the contents of the working copy into the target path. */
SVN_ERR (copy_versioned_files (from, to, revision, force, native_eol,
ctx, pool));
}
if (ctx->notify_func)
(*ctx->notify_func) (ctx->notify_baton,
to,
svn_wc_notify_update_completed,
svn_node_unknown,
NULL,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
edit_revision);
if (result_rev)
*result_rev = edit_revision;
return SVN_NO_ERROR;
}
svn_error_t *
svn_client_export (svn_revnum_t *result_rev,
const char *from,
const char *to,
svn_opt_revision_t *revision,
svn_boolean_t force,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
return svn_client_export2 (result_rev, from, to, revision, force, NULL, ctx,
pool);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?