Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_client/externals.c view on Meta::CPAN
#include "svn_types.h"
#include "svn_error.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_props.h"
#include "svn_config.h"
#include "client.h"
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
/* Remove the directory at LOCAL_ABSPATH from revision control, and do the
* same to any revision controlled directories underneath LOCAL_ABSPATH
* (including directories not referred to by parent svn administrative areas);
* then if LOCAL_ABSPATH is empty afterwards, remove it, else rename it to a
* unique name in the same parent directory.
*
* Pass CANCEL_FUNC, CANCEL_BATON to svn_wc_remove_from_revision_control.
*
* Use SCRATCH_POOL for all temporary allocation.
*/
static svn_error_t *
relegate_dir_external(svn_wc_context_t *wc_ctx,
const char *wri_abspath,
const char *local_abspath,
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_error_t *err = SVN_NO_ERROR;
SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath,
FALSE, scratch_pool, scratch_pool));
err = svn_wc__external_remove(wc_ctx, wri_abspath, local_abspath, FALSE,
cancel_func, cancel_baton, scratch_pool);
if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
{
const char *parent_dir;
const char *dirname;
const char *new_path;
svn_error_clear(err);
err = SVN_NO_ERROR;
svn_dirent_split(&parent_dir, &dirname, local_abspath, scratch_pool);
/* Reserve the new dir name. */
SVN_ERR(svn_io_open_uniquely_named(NULL, &new_path,
parent_dir, dirname, ".OLD",
svn_io_file_del_none,
scratch_pool, scratch_pool));
/* Sigh... We must fall ever so slightly from grace.
Ideally, there would be no window, however brief, when we
don't have a reservation on the new name. Unfortunately,
at least in the Unix (Linux?) version of apr_file_rename(),
you can't rename a directory over a file, because it's just
calling stdio rename(), which says:
ENOTDIR
A component used as a directory in oldpath or newpath
path is not, in fact, a directory. Or, oldpath is
a directory, and newpath exists but is not a directory
So instead, we get the name, then remove the file (ugh), then
rename the directory, hoping that nobody has gotten that name
in the meantime -- which would never happen in real life, so
no big deal.
*/
/* Do our best, but no biggy if it fails. The rename will fail. */
svn_error_clear(svn_io_remove_file2(new_path, TRUE, scratch_pool));
/* Rename. If this is still a working copy we should use the working
copy rename function (to release open handles) */
err = svn_wc__rename_wc(wc_ctx, local_abspath, new_path,
scratch_pool);
if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
{
svn_error_clear(err);
/* And if it is no longer a working copy, we should just rename
it */
err = svn_io_file_rename(local_abspath, new_path, scratch_pool);
}
/* ### TODO: We should notify the user about the rename */
if (notify_func)
{
svn_wc_notify_t *notify;
notify = svn_wc_create_notify(err ? local_abspath : new_path,
svn_wc_notify_left_local_modifications,
scratch_pool);
notify->kind = svn_node_dir;
notify->err = err;
notify_func(notify_baton, notify, scratch_pool);
}
}
return svn_error_trace(err);
}
/* Try to update a directory external at PATH to URL at REVISION.
Use POOL for temporary allocations, and use the client context CTX. */
static svn_error_t *
switch_dir_external(const char *local_abspath,
const char *url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
const char *defining_abspath,
svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
( run in 0.516 second using v1.01-cache-2.11-cpan-39bf76dae61 )