📄 adm_ops.c
字号:
{
apr_pool_t* access_pool = svn_wc_adm_access_pool (parent_access);
SVN_ERR (svn_wc_adm_open2 (&adm_access, parent_access, path,
TRUE, copyfrom_url != NULL ? -1 : 0,
access_pool));
}
/* We're making the same mods we made above, but this time we'll
force the scheduling. Also make sure to undo the
'incomplete' flag which svn_wc_ensure_adm sets by default. */
modify_flags |= SVN_WC__ENTRY_MODIFY_FORCE;
modify_flags |= SVN_WC__ENTRY_MODIFY_INCOMPLETE;
tmp_entry.schedule = is_replace
? svn_wc_schedule_replace
: svn_wc_schedule_add;
tmp_entry.incomplete = FALSE;
SVN_ERR (svn_wc__entry_modify (adm_access, NULL, &tmp_entry,
modify_flags, TRUE, pool));
if (copyfrom_url)
{
/* If this new directory has ancestry, it's not enough to
schedule it for addition with copyfrom args. We also
need to rewrite its ancestor-url, and rewrite the
ancestor-url of ALL its children!
We're doing this because our current commit model (for
hysterical raisins, presumably) assumes an entry's URL is
correct before commit -- i.e. the URL is not tweaked in
the post-commit bumping process. We might want to change
this model someday. */
/* Figure out what the new url should be. */
const char *new_url =
svn_path_url_add_component (parent_entry->url, base_name, pool);
/* Change the entry urls recursively (but not the working rev). */
SVN_ERR (svn_wc__do_update_cleanup (path, adm_access, TRUE, new_url,
SVN_INVALID_REVNUM, NULL,
NULL, FALSE, pool));
/* Recursively add the 'copied' existence flag as well! */
SVN_ERR (mark_tree (adm_access, SVN_WC__ENTRY_MODIFY_COPIED,
svn_wc_schedule_normal, TRUE,
cancel_func,
cancel_baton,
NULL, NULL, /* N/A cuz we aren't deleting */
pool));
/* Clean out the now-obsolete wcprops. */
SVN_ERR (svn_wc__remove_wcprops (adm_access, TRUE, pool));
}
}
/* Report the addition to the caller. */
if (notify_func != NULL)
(*notify_func) (notify_baton, path, svn_wc_notify_add,
kind,
NULL,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
return SVN_NO_ERROR;
}
/* Thoughts on Reversion.
What does is mean to revert a given PATH in a tree? We'll
consider things by their modifications.
Adds
- For files, svn_wc_remove_from_revision_control(), baby.
- Added directories may contain nothing but added children, and
reverting the addition of a directory necessary means reverting
the addition of all the directory's children. Again,
svn_wc_remove_from_revision_control() should do the trick.
Deletes
- Restore properties to their unmodified state.
- For files, restore the pristine contents, and reset the schedule
to 'normal'.
- For directories, reset the schedule to 'normal'. All children
of a directory marked for deletion must also be marked for
deletion, but it's okay for those children to remain deleted even
if their parent directory is restored. That's what the
recursive flag is for.
Replaces
- Restore properties to their unmodified state.
- For files, restore the pristine contents, and reset the schedule
to 'normal'.
- For directories, reset the schedule to normal. A replaced
directory can have deleted children (left over from the initial
deletion), replaced children (children of the initial deletion
now re-added), and added children (new entries under the
replaced directory). Since this is technically an addition, it
necessitates recursion.
Modifications
- Restore properties and, for files, contents to their unmodified
state.
*/
/* Revert ENTRY for NAME in directory represented by ADM_ACCESS, altering
*MODIFY_FLAGS to indicate what parts of the entry were reverted
(for example, if property changes were reverted, then set the
SVN_WC__ENTRY_MODIFY_PROP_TIME bit in MODIFY_FLAGS).
Use POOL for any temporary allocations.*/
static svn_error_t *
revert_admin_things (svn_wc_adm_access_t *adm_access,
const char *name,
svn_wc_entry_t *entry,
apr_uint32_t *modify_flags,
svn_boolean_t use_commit_times,
apr_pool_t *pool)
{
const char *fullpath, *thing, *base_thing;
svn_node_kind_t kind;
svn_boolean_t modified_p;
svn_error_t *err;
apr_time_t tstamp;
apr_array_header_t *propchanges;
svn_boolean_t magic_props_changed = FALSE;
/* Build the full path of the thing we're reverting. */
fullpath = svn_wc_adm_access_path (adm_access);
if (name && (strcmp (name, SVN_WC_ENTRY_THIS_DIR) != 0))
fullpath = svn_path_join (fullpath, name, pool);
/* Check for prop changes. */
SVN_ERR (svn_wc_props_modified_p (&modified_p, fullpath, adm_access, pool));
if (modified_p)
{
svn_node_kind_t working_props_kind;
/* Get the full list of property changes and see if any magic
properties were changed. */
SVN_ERR (svn_wc_get_prop_diffs (&propchanges, NULL, name ? name : "",
adm_access, pool));
/* Determine if any of the propchanges are the "magic" ones that
might require changing the working file. */
{
int i;
for (i = 0; i < propchanges->nelts; i++)
{
svn_prop_t *propchange
= &APR_ARRAY_IDX (propchanges, i, svn_prop_t);
if ((! strcmp (propchange->name, SVN_PROP_EXECUTABLE))
|| (! strcmp (propchange->name, SVN_PROP_KEYWORDS))
|| (! strcmp (propchange->name, SVN_PROP_EOL_STYLE))
|| (! strcmp (propchange->name, SVN_PROP_SPECIAL)))
magic_props_changed = TRUE;
}
}
SVN_ERR (svn_wc__prop_path (&thing, fullpath, adm_access, FALSE, pool));
SVN_ERR (svn_wc__prop_base_path (&base_thing, fullpath, adm_access, FALSE,
pool));
/* There may be a base props file but no working props file, if
the mod was that the working file was `R'eplaced by a new
file with no props. */
SVN_ERR (svn_io_check_path (thing, &working_props_kind, pool));
/* If there is a pristing property file, copy it out as the
working property file, else just remove the working property
file. */
SVN_ERR (svn_io_check_path (base_thing, &kind, pool));
if (kind == svn_node_file)
{
if ((working_props_kind == svn_node_file)
&& (err = svn_wc__prep_file_for_replacement (thing, FALSE, pool)))
return svn_error_quick_wrap
(err, apr_psprintf (pool, _("Error restoring props for '%s'"),
fullpath));
if ((err = svn_io_copy_file (base_thing, thing, FALSE, pool)))
return svn_error_quick_wrap
(err, apr_psprintf (pool, _("Error restoring props for '%s'"),
fullpath));
SVN_ERR (svn_io_file_affected_time (&tstamp, thing, pool));
entry->prop_time = tstamp;
}
else if (working_props_kind == svn_node_file)
{
if ((err = svn_io_remove_file (thing, pool)))
return svn_error_quick_wrap
(err, apr_psprintf (pool, _("Error removing props for '%s'"),
fullpath));
}
/* Modify our entry structure. */
*modify_flags |= SVN_WC__ENTRY_MODIFY_PROP_TIME;
}
else if (entry->schedule == svn_wc_schedule_replace)
{
/* Edge case: we're reverting a replacement, and
svn_wc_props_modified_p thinks there's no property mods.
However, because of the scheduled replacement,
svn_wc_props_modified_p is deliberately ignoring the
base-props; it's "no" answer simply means that there are no
working props. It's *still* possible that the base-props
exist, however, from the original replaced file. If they do,
then we need to restore them. */
SVN_ERR (svn_wc__prop_path (&thing, fullpath, adm_access, FALSE, pool));
SVN_ERR (svn_wc__prop_base_path (&base_thing, fullpath, adm_access, FALSE,
pool));
SVN_ERR (svn_io_check_path (base_thing, &kind, pool));
if (kind == svn_node_file)
{
if ((err = svn_io_copy_file (base_thing, thing, FALSE, pool)))
return svn_error_quick_wrap
(err, apr_psprintf (pool, _("Error restoring props for '%s'"),
fullpath));
SVN_ERR (svn_io_file_affected_time (&tstamp, thing, pool));
entry->prop_time = tstamp;
*modify_flags |= SVN_WC__ENTRY_MODIFY_PROP_TIME;
}
}
if (entry->kind == svn_node_file)
{
SVN_ERR (svn_io_check_path (fullpath, &kind, pool));
base_thing = svn_wc__text_base_path (fullpath, 0, pool);
if (! magic_props_changed)
SVN_ERR (svn_wc_text_modified_p (&modified_p, fullpath, TRUE,
adm_access, pool));
if ((modified_p) || (kind == svn_node_none) || (magic_props_changed))
{
/* If there are textual mods (or if the working file is
missing altogether), copy the text-base out into
the working copy, and update the timestamp in the entries
file. */
svn_subst_keywords_t *keywords;
const char *eol;
svn_boolean_t special;
SVN_ERR (svn_wc__get_eol_style (NULL, &eol, fullpath, adm_access,
pool));
SVN_ERR (svn_wc__get_keywords (&keywords, fullpath, adm_access, NULL,
pool));
SVN_ERR (svn_wc__get_special (&special, fullpath, adm_access, pool));
/* When copying the text-base out to the working copy, make
sure to do any eol translations or keyword substitutions,
as dictated by the property values. If these properties
are turned off, then this is just a normal copy. */
if ((err = svn_subst_copy_and_translate2 (base_thing,
fullpath,
eol,
FALSE, /* don't repair */
keywords,
TRUE, /* expand keywords */
special,
pool)))
return svn_error_quick_wrap
(err, apr_psprintf (pool, _("Error restoring text for '%s'"),
fullpath));
/* If necessary, tweak the new working file's executable bit. */
SVN_ERR (svn_wc__maybe_set_executable (NULL, fullpath, adm_access,
pool));
/* Possibly set the timestamp to last-commit-time, rather
than the 'now' time that already exists. */
if (use_commit_times && (! special))
{
SVN_ERR (svn_io_set_file_affected_time (entry->cmt_date,
fullpath, pool));
tstamp = entry->cmt_date;
}
else
{
SVN_ERR (svn_io_file_affected_time (&tstamp, fullpath, pool));
}
/* Modify our entry structure. */
*modify_flags |= SVN_WC__ENTRY_MODIFY_TEXT_TIME;
entry->text_time = tstamp;
}
}
/* Remove conflict state (and conflict files), if any. */
if (entry->prejfile || entry->conflict_old
|| entry->conflict_new || entry->conflict_wrk)
{
const char *rmfile;
/* Handle the three possible text conflict files. */
if (entry->conflict_old)
{
rmfile = svn_path_join (svn_wc_adm_access_path (adm_access),
entry->conflict_old, pool);
SVN_ERR (remove_file_if_present (rmfile, pool));
*modify_flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_OLD;
}
if (entry->conflict_new)
{
rmfile = svn_path_join (svn_wc_adm_access_path (adm_access),
entry->conflict_new, pool);
SVN_ERR (remove_file_if_present (rmfile, pool));
*modify_flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_NEW;
}
if (entry->conflict_wrk)
{
rmfile = svn_path_join (svn_wc_adm_access_path (adm_access),
entry->conflict_wrk, pool);
SVN_ERR (remove_file_if_present (rmfile, pool));
*modify_flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_WRK;
}
/* Remove the prej-file if the entry lists one (and it exists) */
if (entry->prejfile)
{
rmfile = svn_path_join (svn_wc_adm_access_path (adm_access),
entry->prejfile, pool);
SVN_ERR (remove_file_if_present (rmfile, pool));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -