📄 adm_ops.c
字号:
*modify_flags |= SVN_WC__ENTRY_MODIFY_PREJFILE;
}
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc_revert (const char *path,
svn_wc_adm_access_t *parent_access,
svn_boolean_t recursive,
svn_boolean_t use_commit_times,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func_t notify_func,
void *notify_baton,
apr_pool_t *pool)
{
svn_node_kind_t kind;
const char *p_dir = NULL, *bname = NULL;
const svn_wc_entry_t *entry;
svn_wc_entry_t *tmp_entry;
svn_boolean_t wc_root = FALSE, reverted = FALSE;
apr_uint32_t modify_flags = 0;
svn_wc_adm_access_t *dir_access;
/* Check cancellation here, so recursive calls get checked early. */
if (cancel_func)
SVN_ERR (cancel_func (cancel_baton));
SVN_ERR (svn_wc_adm_probe_retrieve (&dir_access, parent_access, path, pool));
/* Safeguard 1: is this a versioned resource? */
SVN_ERR (svn_wc_entry (&entry, path, dir_access, FALSE, pool));
if (! entry)
return svn_error_createf
(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
_("Cannot revert: '%s' is not under version control"), path);
/* Safeguard 1.5: is this a missing versioned directory? */
if (entry->kind == svn_node_dir)
{
svn_node_kind_t disk_kind;
SVN_ERR (svn_io_check_path (path, &disk_kind, pool));
if ((disk_kind != svn_node_dir)
&& (entry->schedule != svn_wc_schedule_add))
{
/* When the directory itself is missing, we can't revert
without hitting the network. Someday a '--force' option
will make this happen. For now, send notification of the
failure. */
if (notify_func != NULL)
(*notify_func) (notify_baton, path,
svn_wc_notify_failed_revert,
svn_node_unknown,
NULL,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
return SVN_NO_ERROR;
}
}
/* Safeguard 2: can we handle this node kind? */
if ((entry->kind != svn_node_file) && (entry->kind != svn_node_dir))
return svn_error_createf
(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Cannot revert '%s': unsupported entry node kind"), path);
/* Safeguard 3: can we deal with the node kind of PATH current in
the working copy? */
SVN_ERR (svn_io_check_path (path, &kind, pool));
if ((kind != svn_node_none)
&& (kind != svn_node_file)
&& (kind != svn_node_dir))
return svn_error_createf
(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Cannot revert '%s': unsupported node kind in working copy"), path);
/* For directories, determine if PATH is a WC root so that we can
tell if it is safe to split PATH into a parent directory and
basename. For files, we always do this split. */
if (kind == svn_node_dir)
SVN_ERR (svn_wc_is_wc_root (&wc_root, path, dir_access, pool));
if (! wc_root)
{
/* Split the base_name from the parent path. */
svn_path_split (path, &p_dir, &bname, pool);
}
tmp_entry = svn_wc_entry_dup (entry, pool);
/* Additions. */
if (entry->schedule == svn_wc_schedule_add)
{
/* Before removing item from revision control, notice if the
entry is in a 'deleted' state; this is critical for
directories, where this state only exists in its parent's
entry. */
svn_boolean_t was_deleted = FALSE;
const char *parent, *basey;
svn_path_split (path, &parent, &basey, pool);
if (entry->kind == svn_node_file)
{
was_deleted = entry->deleted;
SVN_ERR (svn_wc_remove_from_revision_control (parent_access, bname,
FALSE, FALSE,
cancel_func,
cancel_baton,
pool));
}
else if (entry->kind == svn_node_dir)
{
apr_hash_t *entries;
const svn_wc_entry_t *parents_entry;
/*
* We are trying to revert the current directory which is
* scheduled for addition. This is supposed to fail (Issue #854)
* */
if (path[0] == '\0')
{
return svn_error_create (SVN_ERR_WC_INVALID_OP_ON_CWD, NULL,
_("Cannot revert addition of current directory; "
"please try again from the parent directory"));
}
SVN_ERR (svn_wc_entries_read (&entries, parent_access, TRUE, pool));
parents_entry = apr_hash_get (entries, basey, APR_HASH_KEY_STRING);
if (parents_entry)
was_deleted = parents_entry->deleted;
if (kind == svn_node_none)
{
/* Schedule add but missing, just remove the entry */
svn_wc__entry_remove (entries, basey);
SVN_ERR (svn_wc__entries_write (entries, parent_access, pool));
}
else
SVN_ERR (svn_wc_remove_from_revision_control
(dir_access, SVN_WC_ENTRY_THIS_DIR, FALSE, FALSE,
cancel_func, cancel_baton, pool));
}
else /* Else it's `none', or something exotic like a symlink... */
return svn_error_createf
(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
_("Unknown or unexpected kind for path '%s'"), path);
/* Recursivity is taken care of by svn_wc_remove_from_revision_control,
and we've definitely reverted PATH at this point. */
recursive = FALSE;
reverted = TRUE;
/* If the removed item was *also* in a 'deleted' state, make
sure we leave just a plain old 'deleted' entry behind in the
parent. */
if (was_deleted)
{
svn_wc_entry_t *tmpentry;
tmpentry = apr_pcalloc (pool, sizeof(*tmpentry));
tmpentry->kind = entry->kind;
tmpentry->deleted = TRUE;
if (entry->kind == svn_node_dir)
SVN_ERR (svn_wc__entry_modify (parent_access, basey, tmpentry,
SVN_WC__ENTRY_MODIFY_KIND
| SVN_WC__ENTRY_MODIFY_DELETED,
TRUE, pool));
else
SVN_ERR (svn_wc__entry_modify (parent_access, bname, tmpentry,
SVN_WC__ENTRY_MODIFY_KIND
| SVN_WC__ENTRY_MODIFY_DELETED,
TRUE, pool));
}
}
/* Regular prop and text edit. */
else if (entry->schedule == svn_wc_schedule_normal)
{
/* Revert the prop and text mods (if any). */
if (entry->kind == svn_node_file)
SVN_ERR (revert_admin_things (parent_access, bname, tmp_entry,
&modify_flags, use_commit_times, pool));
if (entry->kind == svn_node_dir)
SVN_ERR (revert_admin_things (dir_access, NULL, tmp_entry,
&modify_flags, use_commit_times, pool));
}
/* Deletions and replacements. */
else if ((entry->schedule == svn_wc_schedule_delete)
|| (entry->schedule == svn_wc_schedule_replace))
{
/* Revert the prop and text mods (if any). */
if (entry->kind == svn_node_file)
SVN_ERR (revert_admin_things (parent_access, bname, tmp_entry,
&modify_flags, use_commit_times, pool));
if (entry->kind == svn_node_dir)
SVN_ERR (revert_admin_things (dir_access, NULL, tmp_entry,
&modify_flags, use_commit_times, pool));
modify_flags |= SVN_WC__ENTRY_MODIFY_SCHEDULE;
}
/* All our disk modifications should be finished by now. Let's
update our entries files. */
if (modify_flags)
{
/* Force recursion on replaced directories. */
if ((entry->kind == svn_node_dir)
&& (entry->schedule == svn_wc_schedule_replace))
recursive = TRUE;
/* Reset the schedule to normal. */
tmp_entry->schedule = svn_wc_schedule_normal;
tmp_entry->conflict_old = NULL;
tmp_entry->conflict_new = NULL;
tmp_entry->conflict_wrk = NULL;
tmp_entry->prejfile = NULL;
if (! wc_root)
SVN_ERR (svn_wc__entry_modify (parent_access, bname, tmp_entry,
modify_flags
| SVN_WC__ENTRY_MODIFY_FORCE,
TRUE, pool));
/* For directories, reset the schedule to normal in the
directory itself. */
if (entry->kind == svn_node_dir)
{
SVN_ERR (svn_wc__entry_modify (dir_access, NULL, tmp_entry,
modify_flags
| SVN_WC__ENTRY_MODIFY_FORCE,
TRUE, pool));
}
/* Note that this was reverted. */
reverted = TRUE;
}
/* If PATH was reverted, tell our client that. */
if ((notify_func != NULL) && reverted)
(*notify_func) (notify_baton, path, svn_wc_notify_revert,
svn_node_unknown,
NULL, /* ### any way to get the mime type? */
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
/* Finally, recurse if requested. */
if (recursive && (entry->kind == svn_node_dir))
{
apr_hash_t *entries;
apr_hash_index_t *hi;
apr_pool_t *subpool = svn_pool_create (pool);
SVN_ERR (svn_wc_entries_read (&entries, dir_access, FALSE, pool));
for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
{
const void *key;
const char *keystring;
const char *full_entry_path;
/* Get the next entry */
apr_hash_this (hi, &key, NULL, NULL);
keystring = key;
/* Skip "this dir" */
if (! strcmp (keystring, SVN_WC_ENTRY_THIS_DIR))
continue;
/* Add the entry name to FULL_ENTRY_PATH. */
full_entry_path = svn_path_join (path, keystring, subpool);
/* Revert the entry. */
SVN_ERR (svn_wc_revert (full_entry_path, dir_access, TRUE,
use_commit_times,
cancel_func, cancel_baton,
notify_func, notify_baton, subpool));
svn_pool_clear (subpool);
}
svn_pool_destroy (subpool);
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc_get_pristine_copy_path (const char *path,
const char **pristine_path,
apr_pool_t *pool)
{
*pristine_path = svn_wc__text_base_path (path, FALSE, pool);
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc_remove_from_revision_control (svn_wc_adm_access_t *adm_access,
const char *name,
svn_boolean_t destroy_wf,
svn_boolean_t instant_error,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
{
svn_error_t *err;
svn_boolean_t is_file;
svn_boolean_t left_something = FALSE;
apr_hash_t *entries = NULL;
const char *full_path = apr_pstrdup (pool,
svn_wc_adm_access_path (adm_access));
/* Check cancellation here, so recursive calls get checked early. */
if (cancel_func)
SVN_ERR (cancel_func (cancel_baton));
/* NAME is either a file's basename or SVN_WC_ENTRY_THIS_DIR. */
is_file = (strcmp (name, SVN_WC_ENTRY_THIS_DIR)) ? TRUE : FALSE;
if (is_file)
{
svn_boolean_t text_modified_p;
full_path = svn_path_join (full_path, name, pool);
/* Check for local mods. before removing entry */
SVN_ERR (svn_wc_text_modified_p (&text_modified_p, full_path,
FALSE, adm_access, pool));
if (text_modified_p && instant_error)
return svn_error_createf (SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
_("File '%s' has local modifications"),
name);
/* Remove NAME from PATH's entries file: */
SVN_ERR (svn_wc_entries_read (&entries, adm_access, TRUE, pool
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -