#include "svn_path.h"
#include "svn_wc.h"
#include "svn_client.h"
#include "svn_dirent_uri.h"
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_time.h"
#include "svn_config.h"
#include "client.h"
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
struct revert_with_write_lock_baton {
const char *local_abspath;
svn_depth_t depth;
svn_boolean_t use_commit_times;
const apr_array_header_t *changelists;
svn_client_ctx_t *ctx;
};
static svn_error_t *
revert(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
struct revert_with_write_lock_baton *b = baton;
svn_error_t *err;
err = svn_wc_revert4(b->ctx->wc_ctx,
b->local_abspath,
b->depth,
b->use_commit_times,
b->changelists,
b->ctx->cancel_func, b->ctx->cancel_baton,
b->ctx->notify_func2, b->ctx->notify_baton2,
scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_ENTRY_NOT_FOUND
|| err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE
|| err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
{
if (b->ctx->notify_func2)
(*b->ctx->notify_func2)(
b->ctx->notify_baton2,
svn_wc_create_notify(b->local_abspath, svn_wc_notify_skip,
scratch_pool),
scratch_pool);
svn_error_clear(err);
}
else
return svn_error_trace(err);
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_client_revert2(const apr_array_header_t *paths,
svn_depth_t depth,
const apr_array_header_t *changelists,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
apr_pool_t *subpool;
svn_error_t *err = SVN_NO_ERROR;
int i;
svn_config_t *cfg;
svn_boolean_t use_commit_times;
struct revert_with_write_lock_baton baton;
for (i = 0; i < paths->nelts; i++)
{
const char *path = APR_ARRAY_IDX(paths, i, const char *);
if (svn_path_is_url(path))
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
_("'%s' is not a local path"), path);
}
cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING) : NULL;
SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
SVN_CONFIG_SECTION_MISCELLANY,
SVN_CONFIG_OPTION_USE_COMMIT_TIMES,
FALSE));
subpool = svn_pool_create(pool);
for (i = 0; i < paths->nelts; i++)
{
const char *path = APR_ARRAY_IDX(paths, i, const char *);
const char *local_abspath, *lock_target;
svn_boolean_t wc_root;
svn_pool_clear(subpool);
if ((ctx->cancel_func)
&& ((err = ctx->cancel_func(ctx->cancel_baton))))
goto errorful;
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
baton.local_abspath = local_abspath;
baton.depth = depth;
baton.use_commit_times = use_commit_times;
baton.changelists = changelists;
baton.ctx = ctx;
SVN_ERR(svn_wc__strictly_is_wc_root(&wc_root, ctx->wc_ctx,
local_abspath, pool));
lock_target = wc_root ? local_abspath
: svn_dirent_dirname(local_abspath, pool);
err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx,
lock_target, FALSE, pool, pool);
if (err)
goto errorful;
}
errorful:
if (!use_commit_times)
{
const char* sleep_path = NULL;
if (paths->nelts == 1)
sleep_path = APR_ARRAY_IDX(paths, 0, const char *);
svn_io_sleep_for_timestamps(sleep_path, subpool);
}
svn_pool_destroy(subpool);
return svn_error_trace(err);
}