📄 adm_ops.c
字号:
} } /* If not schedule replace, or no revert props, use the normal base-props and working props. */ if (! baseprops) { svn_boolean_t modified; /* Check for prop changes. */ SVN_ERR(svn_wc_props_modified_p(&modified, fullpath, adm_access, pool)); if (modified) { apr_array_header_t *propchanges; /* Get the full list of property changes and see if any magic properties were changed. */ SVN_ERR(svn_wc_get_prop_diffs(&propchanges, &baseprops, fullpath, adm_access, pool)); /* Determine if any of the propchanges are the "magic" ones that might require changing the working file. */ reinstall_working = svn_wc__has_magic_property(propchanges); } } /* Reinstall props if we need to. Only rewrite the baseprops, if we're reverting a replacement. This is just an optimization. */ if (baseprops) { SVN_ERR(svn_wc__install_props(&log_accum, adm_access, name, baseprops, baseprops, entry->schedule == svn_wc_schedule_replace, pool)); *reverted = TRUE; } /* Clean up the copied state if this is a replacement. */ if (entry->schedule == svn_wc_schedule_replace && entry->copied) { flags |= SVN_WC__ENTRY_MODIFY_COPIED; tmp_entry.copied = FALSE; *reverted = TRUE; } /* Deal with the contents. */ if (entry->kind == svn_node_file) { svn_node_kind_t base_kind; const char *base_thing; svn_boolean_t tgt_modified; /* If the working file is missing, we need to reinstall it. */ if (! reinstall_working) { svn_node_kind_t kind; SVN_ERR(svn_io_check_path(fullpath, &kind, pool)); if (kind == svn_node_none) reinstall_working = TRUE; } base_thing = svn_wc__text_base_path(name, FALSE, pool); /* Check for text base presence. */ SVN_ERR(svn_io_check_path(svn_path_join(adm_path, base_thing, pool), &base_kind, pool)); if (base_kind != svn_node_file) return svn_error_createf(APR_ENOENT, NULL, _("Error restoring text for '%s'"), svn_path_local_style(fullpath, pool)); /* Look for a revert base file. If it exists use it for * the text base for the file. If it doesn't use the normal * text base. */ SVN_ERR(svn_wc__loggy_move (&log_accum, &tgt_modified, adm_access, svn_wc__text_revert_path(name, FALSE, pool), base_thing, FALSE, pool)); reinstall_working = reinstall_working || tgt_modified; /* A shortcut: since we will translate when reinstall_working, we don't need to check if the working file is modified */ if (! reinstall_working) SVN_ERR(svn_wc__text_modified_internal_p(&reinstall_working, fullpath, FALSE, adm_access, FALSE, pool)); if (reinstall_working) { /* 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_ERR(svn_wc__loggy_copy(&log_accum, NULL, adm_access, svn_wc__copy_translate, base_thing, name, FALSE, pool)); /* Possibly set the timestamp to last-commit-time, rather than the 'now' time that already exists. */ if (use_commit_times && entry->cmt_date) SVN_ERR(svn_wc__loggy_set_timestamp (&log_accum, adm_access, name, svn_time_to_cstring(entry->cmt_date, pool), pool)); SVN_ERR(svn_wc__loggy_set_entry_timestamp_from_wc (&log_accum, adm_access, name, SVN_WC__ENTRY_ATTR_TEXT_TIME, pool)); *reverted = TRUE; } } /* Remove conflict state (and conflict files), if any. Handle the three possible text conflict files. */ if (entry->conflict_old) { flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_OLD; tmp_entry.conflict_old = NULL; SVN_ERR(svn_wc__loggy_remove(&log_accum, adm_access, entry->conflict_old, pool)); } if (entry->conflict_new) { flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_NEW; tmp_entry.conflict_new = NULL; SVN_ERR(svn_wc__loggy_remove(&log_accum, adm_access, entry->conflict_new, pool)); } if (entry->conflict_wrk) { flags |= SVN_WC__ENTRY_MODIFY_CONFLICT_WRK; tmp_entry.conflict_wrk = NULL; SVN_ERR(svn_wc__loggy_remove(&log_accum, adm_access, entry->conflict_wrk, pool)); } /* Remove the prej-file if the entry lists one (and it exists) */ if (entry->prejfile) { flags |= SVN_WC__ENTRY_MODIFY_PREJFILE; tmp_entry.prejfile = NULL; SVN_ERR(svn_wc__loggy_remove(&log_accum, adm_access, entry->prejfile, pool)); } /* Reset schedule attribute to svn_wc_schedule_normal. */ if (entry->schedule != svn_wc_schedule_normal) { flags |= SVN_WC__ENTRY_MODIFY_SCHEDULE; tmp_entry.schedule = svn_wc_schedule_normal; *reverted = TRUE; } SVN_ERR(svn_wc__loggy_entry_modify(&log_accum, adm_access, name, &tmp_entry, flags, pool)); /* Don't run log if nothing to change. */ if (!svn_stringbuf_isempty(log_accum)) { SVN_ERR(svn_wc__write_log(adm_access, 0, log_accum, pool)); SVN_ERR(svn_wc__run_log(adm_access, NULL, pool)); } return SVN_NO_ERROR;}svn_error_t *svn_wc_revert2(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_func2_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_boolean_t wc_root = FALSE, reverted = FALSE; 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"), svn_path_local_style(path, pool)); /* 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, svn_wc_create_notify(path, svn_wc_notify_failed_revert, pool), pool); 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"), svn_path_local_style(path, pool)); /* 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"), svn_path_local_style(path, pool)); /* 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); } /* 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'"), svn_path_local_style(path, pool)); /* 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. */ /* Deletions and replacements. */ else if (entry->schedule == svn_wc_schedule_normal || 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, entry, &reverted, use_commit_times, pool)); if (entry->kind == svn_node_dir) S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -