#include <string.h>
#include <apr_pools.h>
#include <apr_file_io.h>
#include <apr_hash.h>
#include "svn_types.h"
#include "svn_pools.h"
#include "svn_wc.h"
#include "svn_io.h"
#include "svn_delta.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "private/svn_wc_private.h"
#include "wc.h"
#include "adm_files.h"
#include "translate.h"
#include "workqueue.h"
#include "conflicts.h"
#include "svn_private_config.h"
static svn_error_t *
restore_file(svn_wc__db_t *db,
const char *local_abspath,
svn_boolean_t use_commit_times,
svn_boolean_t remove_text_conflicts,
apr_pool_t *scratch_pool)
{
svn_skel_t *work_item;
SVN_ERR(svn_wc__wq_build_file_install(&work_item,
db, local_abspath,
NULL ,
use_commit_times,
TRUE ,
scratch_pool, scratch_pool));
SVN_ERR(svn_wc__db_wq_add(db,
svn_dirent_dirname(local_abspath, scratch_pool),
work_item, scratch_pool));
SVN_ERR(svn_wc__wq_run(db, local_abspath,
NULL, NULL,
scratch_pool));
if (remove_text_conflicts)
SVN_ERR(svn_wc__resolve_text_conflict(db, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc_restore(svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_boolean_t use_commit_times,
apr_pool_t *scratch_pool)
{
svn_wc__db_status_t status;
svn_wc__db_kind_t kind;
svn_node_kind_t disk_kind;
SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, scratch_pool));
if (disk_kind != svn_node_none)
return svn_error_createf(SVN_ERR_WC_PATH_FOUND, NULL,
_("The existing node '%s' can not be restored."),
svn_dirent_local_style(local_abspath,
scratch_pool));
SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
wc_ctx->db, local_abspath,
scratch_pool, scratch_pool));
if (status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL,
wc_ctx->db, local_abspath,
scratch_pool, scratch_pool));
if (status != svn_wc__db_status_normal
&& status != svn_wc__db_status_copied
&& status != svn_wc__db_status_moved_here
&& !(kind == svn_wc__db_kind_dir
&& (status == svn_wc__db_status_added
|| status == svn_wc__db_status_incomplete)))
{
return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
_("The node '%s' can not be restored."),
svn_dirent_local_style(local_abspath,
scratch_pool));
}
if (kind == svn_wc__db_kind_file || kind == svn_wc__db_kind_symlink)
SVN_ERR(restore_file(wc_ctx->db, local_abspath, use_commit_times, FALSE,
scratch_pool));
else
SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
restore_node(svn_wc__db_t *db,
const char *local_abspath,
svn_wc__db_kind_t kind,
svn_boolean_t use_commit_times,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool)
{
if (kind == svn_wc__db_kind_file || kind == svn_wc__db_kind_symlink)
{
SVN_ERR(restore_file(db, local_abspath, use_commit_times, TRUE,
scratch_pool));
}
else if (kind == svn_wc__db_kind_dir)
{
SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool));
}
if (notify_func != NULL)
{
svn_wc_notify_t *notify = svn_wc_create_notify(local_abspath,
svn_wc_notify_restore,
scratch_pool);
notify->kind = svn_node_file;
(*notify_func)(notify_baton, notify, scratch_pool);
}
return SVN_NO_ERROR;
}
static svn_error_t *
report_revisions_and_depths(svn_wc__db_t *db,
const char *dir_abspath,
const char *report_relpath,
svn_revnum_t dir_rev,
const char *dir_repos_relpath,
const char *dir_repos_root,
svn_depth_t dir_depth,
const svn_ra_reporter3_t *reporter,
void *report_baton,
svn_boolean_t restore_files,
svn_depth_t depth,
svn_boolean_t honor_depth_exclude,
svn_boolean_t depth_compatibility_trick,
svn_boolean_t report_everything,
svn_boolean_t use_commit_times,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool)
{
apr_hash_t *base_children;
apr_hash_t *dirents;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_hash_index_t *hi;
svn_error_t *err;
SVN_ERR(svn_wc__db_base_get_children_info(&base_children, db, dir_abspath,
scratch_pool, iterpool));
if (restore_files)
{
err = svn_io_get_dirents3(&dirents, dir_abspath, TRUE,
scratch_pool, scratch_pool);
if (err && (APR_STATUS_IS_ENOENT(err->apr_err)
|| SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)))
{
svn_error_clear(err);
dirents = apr_hash_make(scratch_pool);
}
else
SVN_ERR(err);
}
else
dirents = NULL;
for (hi = apr_hash_first(scratch_pool, base_children);
hi != NULL;
hi = apr_hash_next(hi))
{
const char *child = svn__apr_hash_index_key(hi);
const char *this_report_relpath;
const char *this_abspath;
svn_boolean_t this_switched = FALSE;
struct svn_wc__db_base_info_t *ths = svn__apr_hash_index_val(hi);
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
svn_pool_clear(iterpool);
this_report_relpath = svn_relpath_join(report_relpath, child, iterpool);
this_abspath = svn_dirent_join(dir_abspath, child, iterpool);
if (ths->update_root)
{
;
continue;
}
if (ths->status == svn_wc__db_status_excluded)
{
if (honor_depth_exclude)
{
SVN_ERR(reporter->set_path(report_baton,
this_report_relpath,
dir_rev,
svn_depth_exclude,
FALSE,
NULL,
iterpool));
}
else
{
if (! report_everything)
SVN_ERR(reporter->delete_path(report_baton,
this_report_relpath, iterpool));
}
continue;
}
if (ths->status == svn_wc__db_status_server_excluded
|| ths->status == svn_wc__db_status_not_present)
{
if (! report_everything)
SVN_ERR(reporter->delete_path(report_baton, this_report_relpath,
iterpool));
continue;
}
if (restore_files
&& apr_hash_get(dirents, child, APR_HASH_KEY_STRING) == NULL)
{
svn_wc__db_status_t wrk_status;
svn_wc__db_kind_t wrk_kind;
SVN_ERR(svn_wc__db_read_info(&wrk_status, &wrk_kind, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
db, this_abspath, iterpool, iterpool));
if (wrk_status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(&wrk_status, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
db, this_abspath,
iterpool, iterpool));
if (wrk_status == svn_wc__db_status_normal
|| wrk_status == svn_wc__db_status_copied
|| wrk_status == svn_wc__db_status_moved_here
|| (wrk_kind == svn_wc__db_kind_dir
&& (wrk_status == svn_wc__db_status_added
|| wrk_status == svn_wc__db_status_incomplete)))
{
svn_node_kind_t dirent_kind;
SVN_ERR(svn_io_check_path(this_abspath, &dirent_kind, iterpool));
if (dirent_kind == svn_node_none)
{
SVN_ERR(restore_node(db, this_abspath, wrk_kind,
use_commit_times, notify_func,
notify_baton, iterpool));
}
}
}
if (!ths->repos_relpath)
{
ths->repos_relpath = svn_relpath_join(dir_repos_relpath, child,
iterpool);
}
else
{
const char *childname = svn_relpath__is_child(dir_repos_relpath,
ths->repos_relpath,
NULL);
if (childname == NULL || strcmp(childname, child) != 0)
{
this_switched = TRUE;
}
}
if (ths->depth == svn_depth_unknown)
ths->depth = svn_depth_infinity;
if (ths->kind == svn_wc__db_kind_file ||
ths->kind == svn_wc__db_kind_symlink)
{
if (report_everything)
{
if (this_switched)
SVN_ERR(reporter->link_path(report_baton,
this_report_relpath,
svn_path_url_add_component2(
dir_repos_root,
ths->repos_relpath, iterpool),
ths->revnum,
ths->depth,
FALSE,
ths->lock ? ths->lock->token : NULL,
iterpool));
else
SVN_ERR(reporter->set_path(report_baton,
this_report_relpath,
ths->revnum,
ths->depth,
FALSE,
ths->lock ? ths->lock->token : NULL,
iterpool));
}
else if (this_switched)
SVN_ERR(reporter->link_path(report_baton,
this_report_relpath,
svn_path_url_add_component2(
dir_repos_root,
ths->repos_relpath, iterpool),
ths->revnum,
ths->depth,
FALSE,
ths->lock ? ths->lock->token : NULL,
iterpool));
else if (ths->revnum != dir_rev
|| ths->lock
|| dir_depth == svn_depth_empty)
SVN_ERR(reporter->set_path(report_baton,
this_report_relpath,
ths->revnum,
ths->depth,
FALSE,
ths->lock ? ths->lock->token : NULL,
iterpool));
}
else if (ths->kind == svn_wc__db_kind_dir
&& (depth > svn_depth_files
|| depth == svn_depth_unknown))
{
svn_boolean_t is_incomplete;
svn_boolean_t start_empty;
svn_depth_t report_depth = ths->depth;
is_incomplete = (ths->status == svn_wc__db_status_incomplete);
start_empty = is_incomplete;
if (!SVN_DEPTH_IS_RECURSIVE(depth))
report_depth = svn_depth_empty;
if (is_incomplete && !SVN_IS_VALID_REVNUM(ths->revnum))
ths->revnum = dir_rev;
if (depth_compatibility_trick
&& ths->depth <= svn_depth_files
&& depth > ths->depth)
{
start_empty = TRUE;
}
if (report_everything)
{
if (this_switched)
SVN_ERR(reporter->link_path(report_baton,
this_report_relpath,
svn_path_url_add_component2(
dir_repos_root,
ths->repos_relpath, iterpool),
ths->revnum,
report_depth,
start_empty,
ths->lock ? ths->lock->token
: NULL,
iterpool));
else
SVN_ERR(reporter->set_path(report_baton,
this_report_relpath,
ths->revnum,
report_depth,
start_empty,
ths->lock ? ths->lock->token : NULL,
iterpool));
}
else if (this_switched)
{
SVN_ERR(reporter->link_path(report_baton,
this_report_relpath,
svn_path_url_add_component2(
dir_repos_root,
ths->repos_relpath, iterpool),
ths->revnum,
report_depth,
start_empty,
ths->lock ? ths->lock->token : NULL,
iterpool));
}
else if (ths->revnum != dir_rev
|| ths->lock
|| is_incomplete
|| dir_depth == svn_depth_empty
|| dir_depth == svn_depth_files
|| (dir_depth == svn_depth_immediates
&& ths->depth != svn_depth_empty)
|| (ths->depth < svn_depth_infinity
&& SVN_DEPTH_IS_RECURSIVE(depth)))
{
SVN_ERR(reporter->set_path(report_baton,
this_report_relpath,
ths->revnum,
report_depth,
start_empty,
ths->lock ? ths->lock->token : NULL,
iterpool));
}
if (SVN_DEPTH_IS_RECURSIVE(depth))
{
const char *repos_relpath = ths->repos_relpath;
if (repos_relpath == NULL)
{
repos_relpath = svn_relpath_join(dir_repos_relpath, child,
iterpool);
}
SVN_ERR(report_revisions_and_depths(db,
this_abspath,
this_report_relpath,
ths->revnum,
repos_relpath,
dir_repos_root,
ths->depth,
reporter, report_baton,
restore_files, depth,
honor_depth_exclude,
depth_compatibility_trick,
start_empty,
use_commit_times,
cancel_func, cancel_baton,
notify_func, notify_baton,
iterpool));
}
}
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc_crawl_revisions5(svn_wc_context_t *wc_ctx,
const char *local_abspath,
const svn_ra_reporter3_t *reporter,
void *report_baton,
svn_boolean_t restore_files,
svn_depth_t depth,
svn_boolean_t honor_depth_exclude,
svn_boolean_t depth_compatibility_trick,
svn_boolean_t use_commit_times,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = wc_ctx->db;
svn_error_t *fserr, *err;
svn_revnum_t target_rev = SVN_INVALID_REVNUM;
svn_boolean_t start_empty;
svn_wc__db_status_t status;
svn_wc__db_kind_t target_kind;
const char *repos_relpath, *repos_root_url;
svn_depth_t target_depth;
svn_wc__db_lock_t *target_lock;
svn_node_kind_t disk_kind;
svn_depth_t report_depth;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
err = svn_wc__db_base_get_info(&status, &target_kind, &target_rev,
&repos_relpath, &repos_root_url,
NULL, NULL, NULL, NULL, &target_depth,
NULL, NULL, &target_lock,
NULL, NULL,
db, local_abspath, scratch_pool,
scratch_pool);
if (err
|| (status != svn_wc__db_status_normal
&& status != svn_wc__db_status_incomplete))
{
if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
return svn_error_trace(err);
svn_error_clear(err);
if (depth == svn_depth_unknown)
depth = svn_depth_infinity;
SVN_ERR(reporter->set_path(report_baton, "", 0, depth, FALSE,
NULL, scratch_pool));
SVN_ERR(reporter->delete_path(report_baton, "", scratch_pool));
SVN_ERR(reporter->finish_report(report_baton, scratch_pool));
return SVN_NO_ERROR;
}
if (! repos_relpath)
SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url, NULL,
db, local_abspath,
scratch_pool, scratch_pool));
if (target_depth == svn_depth_unknown)
target_depth = svn_depth_infinity;
start_empty = (status == svn_wc__db_status_incomplete);
if (depth_compatibility_trick
&& target_depth <= svn_depth_immediates
&& depth > target_depth)
{
start_empty = TRUE;
}
if (restore_files)
SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, scratch_pool));
else
disk_kind = svn_node_unknown;
if (restore_files
&& disk_kind == svn_node_none)
{
svn_wc__db_status_t wrk_status;
svn_wc__db_kind_t wrk_kind;
err = svn_wc__db_read_info(&wrk_status, &wrk_kind, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL,
db, local_abspath,
scratch_pool, scratch_pool);
if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
{
svn_error_clear(err);
wrk_status = svn_wc__db_status_not_present;
wrk_kind = svn_wc__db_kind_file;
}
else
SVN_ERR(err);
if (wrk_status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(&wrk_status, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
db, local_abspath,
scratch_pool, scratch_pool));
if (wrk_status == svn_wc__db_status_normal
|| wrk_status == svn_wc__db_status_copied
|| wrk_status == svn_wc__db_status_moved_here
|| (wrk_kind == svn_wc__db_kind_dir
&& (wrk_status == svn_wc__db_status_added
|| wrk_status == svn_wc__db_status_incomplete)))
{
SVN_ERR(restore_node(wc_ctx->db, local_abspath,
wrk_kind, use_commit_times,
notify_func, notify_baton,
scratch_pool));
}
}
{
report_depth = target_depth;
if (honor_depth_exclude
&& depth != svn_depth_unknown
&& depth < target_depth)
report_depth = depth;
SVN_ERR(reporter->set_path(report_baton, "", target_rev, report_depth,
start_empty, NULL, scratch_pool));
}
if (target_kind == svn_wc__db_kind_dir)
{
if (depth != svn_depth_empty)
{
err = report_revisions_and_depths(wc_ctx->db,
local_abspath,
"",
target_rev,
repos_relpath,
repos_root_url,
report_depth,
reporter, report_baton,
restore_files, depth,
honor_depth_exclude,
depth_compatibility_trick,
start_empty,
use_commit_times,
cancel_func, cancel_baton,
notify_func, notify_baton,
scratch_pool);
if (err)
goto abort_report;
}
}
else if (target_kind == svn_wc__db_kind_file ||
target_kind == svn_wc__db_kind_symlink)
{
const char *parent_abspath, *base;
svn_wc__db_status_t parent_status;
const char *parent_repos_relpath;
svn_dirent_split(&parent_abspath, &base, local_abspath,
scratch_pool);
err = svn_wc__db_base_get_info(&parent_status, NULL, NULL,
&parent_repos_relpath, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL,
db, parent_abspath,
scratch_pool, scratch_pool);
if (err)
goto abort_report;
if (strcmp(repos_relpath,
svn_relpath_join(parent_repos_relpath, base,
scratch_pool)) != 0)
{
err = reporter->link_path(report_baton,
"",
svn_path_url_add_component2(
repos_root_url,
repos_relpath,
scratch_pool),
target_rev,
svn_depth_infinity,
FALSE,
target_lock ? target_lock->token : NULL,
scratch_pool);
if (err)
goto abort_report;
}
else if (target_lock)
{
err = reporter->set_path(report_baton, "", target_rev,
svn_depth_infinity,
FALSE,
target_lock ? target_lock->token : NULL,
scratch_pool);
if (err)
goto abort_report;
}
}
return svn_error_trace(reporter->finish_report(report_baton, scratch_pool));
abort_report:
if ((fserr = reporter->abort_report(report_baton, scratch_pool)))
{
fserr = svn_error_quick_wrap(fserr, _("Error aborting report"));
svn_error_compose(err, fserr);
}
return svn_error_trace(err);
}
struct copying_stream_baton
{
svn_stream_t *source;
svn_stream_t *target;
};
static svn_error_t *
read_handler_copy(void *baton, char *buffer, apr_size_t *len)
{
struct copying_stream_baton *btn = baton;
SVN_ERR(svn_stream_read(btn->source, buffer, len));
return svn_stream_write(btn->target, buffer, len);
}
static svn_error_t *
close_handler_copy(void *baton)
{
struct copying_stream_baton *btn = baton;
SVN_ERR(svn_stream_close(btn->target));
return svn_stream_close(btn->source);
}
static svn_stream_t *
copying_stream(svn_stream_t *source,
svn_stream_t *target,
apr_pool_t *pool)
{
struct copying_stream_baton *baton;
svn_stream_t *stream;
baton = apr_palloc(pool, sizeof (*baton));
baton->source = source;
baton->target = target;
stream = svn_stream_create(baton, pool);
svn_stream_set_read(stream, read_handler_copy);
svn_stream_set_close(stream, close_handler_copy);
return stream;
}
static svn_error_t *
read_and_checksum_pristine_text(svn_stream_t **stream,
const svn_checksum_t **expected_md5_checksum,
svn_checksum_t **actual_md5_checksum,
svn_wc__db_t *db,
const char *local_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_stream_t *base_stream;
SVN_ERR(svn_wc__get_pristine_contents(&base_stream, NULL, db, local_abspath,
result_pool, scratch_pool));
if (base_stream == NULL)
{
base_stream = svn_stream_empty(result_pool);
*expected_md5_checksum = NULL;
*actual_md5_checksum = NULL;
}
else
{
const svn_checksum_t *expected_md5;
SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, &expected_md5,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
db, local_abspath,
result_pool, scratch_pool));
if (expected_md5 == NULL)
return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
_("Pristine checksum for file '%s' is missing"),
svn_dirent_local_style(local_abspath,
scratch_pool));
if (expected_md5->kind != svn_checksum_md5)
SVN_ERR(svn_wc__db_pristine_get_md5(&expected_md5, db, local_abspath,
expected_md5,
result_pool, scratch_pool));
*expected_md5_checksum = expected_md5;
base_stream = svn_stream_checksummed2(base_stream, actual_md5_checksum,
NULL, svn_checksum_md5, TRUE,
result_pool);
}
*stream = base_stream;
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc__internal_transmit_text_deltas(const char **tempfile,
const svn_checksum_t **new_text_base_md5_checksum,
const svn_checksum_t **new_text_base_sha1_checksum,
svn_wc__db_t *db,
const char *local_abspath,
svn_boolean_t fulltext,
const svn_delta_editor_t *editor,
void *file_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_txdelta_window_handler_t handler;
void *wh_baton;
const svn_checksum_t *expected_md5_checksum;
svn_checksum_t *verify_checksum;
svn_checksum_t *local_md5_checksum;
svn_checksum_t *local_sha1_checksum;
const char *new_pristine_tmp_abspath;
svn_error_t *err;
svn_stream_t *base_stream;
svn_stream_t *local_stream;
SVN_ERR(svn_wc__internal_translated_stream(&local_stream, db,
local_abspath, local_abspath,
SVN_WC_TRANSLATE_TO_NF,
scratch_pool, scratch_pool));
if (tempfile)
{
svn_stream_t *tempstream;
SVN_ERR(svn_stream_open_unique(&tempstream, tempfile,
NULL, svn_io_file_del_none,
result_pool, scratch_pool));
local_stream = copying_stream(local_stream, tempstream, scratch_pool);
}
if (new_text_base_sha1_checksum)
{
svn_stream_t *new_pristine_stream;
SVN_ERR(svn_wc__open_writable_base(&new_pristine_stream,
&new_pristine_tmp_abspath,
NULL, &local_sha1_checksum,
db, local_abspath,
scratch_pool, scratch_pool));
local_stream = copying_stream(local_stream, new_pristine_stream,
scratch_pool);
}
if (! fulltext)
{
SVN_ERR(read_and_checksum_pristine_text(&base_stream,
&expected_md5_checksum,
&verify_checksum,
db, local_abspath,
scratch_pool, scratch_pool));
}
else
{
base_stream = svn_stream_empty(scratch_pool);
expected_md5_checksum = NULL;
verify_checksum = NULL;
}
{
const char *base_digest_hex = NULL;
if (expected_md5_checksum)
base_digest_hex = svn_checksum_to_cstring_display(expected_md5_checksum,
scratch_pool);
SVN_ERR(editor->apply_textdelta(file_baton, base_digest_hex, scratch_pool,
&handler, &wh_baton));
}
err = svn_txdelta_run(base_stream, local_stream,
handler, wh_baton,
svn_checksum_md5, &local_md5_checksum,
NULL, NULL,
scratch_pool, scratch_pool);
err = svn_error_compose_create(err, svn_stream_close(base_stream));
err = svn_error_compose_create(err, svn_stream_close(local_stream));
if (expected_md5_checksum && verify_checksum
&& !svn_checksum_match(expected_md5_checksum, verify_checksum))
{
if (tempfile)
err = svn_error_compose_create(
err,
svn_io_remove_file2(*tempfile, TRUE, scratch_pool));
err = svn_error_compose_create(
svn_checksum_mismatch_err(expected_md5_checksum, verify_checksum,
scratch_pool,
_("Checksum mismatch for text base of '%s'"),
svn_dirent_local_style(local_abspath,
scratch_pool)),
err);
return svn_error_create(SVN_ERR_WC_CORRUPT_TEXT_BASE, err, NULL);
}
SVN_ERR_W(err, apr_psprintf(scratch_pool,
_("While preparing '%s' for commit"),
svn_dirent_local_style(local_abspath,
scratch_pool)));
if (new_text_base_md5_checksum)
*new_text_base_md5_checksum = svn_checksum_dup(local_md5_checksum,
result_pool);
if (new_text_base_sha1_checksum)
{
SVN_ERR(svn_wc__db_pristine_install(db, new_pristine_tmp_abspath,
local_sha1_checksum,
local_md5_checksum,
scratch_pool));
*new_text_base_sha1_checksum = svn_checksum_dup(local_sha1_checksum,
result_pool);
}
return svn_error_trace(
editor->close_file(file_baton,
svn_checksum_to_cstring(local_md5_checksum,
scratch_pool),
scratch_pool));
}
svn_error_t *
svn_wc_transmit_text_deltas3(const svn_checksum_t **new_text_base_md5_checksum,
const svn_checksum_t **new_text_base_sha1_checksum,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_boolean_t fulltext,
const svn_delta_editor_t *editor,
void *file_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
return svn_wc__internal_transmit_text_deltas(NULL,
new_text_base_md5_checksum,
new_text_base_sha1_checksum,
wc_ctx->db, local_abspath,
fulltext, editor,
file_baton, result_pool,
scratch_pool);
}
svn_error_t *
svn_wc__internal_transmit_prop_deltas(svn_wc__db_t *db,
const char *local_abspath,
const svn_delta_editor_t *editor,
void *baton,
apr_pool_t *scratch_pool)
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
int i;
apr_array_header_t *propmods;
svn_wc__db_kind_t kind;
SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE, iterpool));
SVN_ERR(svn_wc__internal_propdiff(&propmods, NULL, db, local_abspath,
scratch_pool, iterpool));
for (i = 0; i < propmods->nelts; i++)
{
const svn_prop_t *p = &APR_ARRAY_IDX(propmods, i, svn_prop_t);
svn_pool_clear(iterpool);
if (kind == svn_wc__db_kind_file)
SVN_ERR(editor->change_file_prop(baton, p->name, p->value,
iterpool));
else
SVN_ERR(editor->change_dir_prop(baton, p->name, p->value,
iterpool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc_transmit_prop_deltas2(svn_wc_context_t *wc_ctx,
const char *local_abspath,
const svn_delta_editor_t *editor,
void *baton,
apr_pool_t *scratch_pool)
{
return svn_wc__internal_transmit_prop_deltas(wc_ctx->db, local_abspath,
editor, baton, scratch_pool);
}