📄 adm_ops.c
字号:
void *cancel_baton, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *pool){ const char *parent_dir, *base_name; const svn_wc_entry_t *orig_entry, *parent_entry; svn_wc_entry_t tmp_entry; svn_boolean_t is_replace = FALSE; svn_node_kind_t kind; apr_uint32_t modify_flags = 0; svn_wc_adm_access_t *adm_access; SVN_ERR(svn_path_check_valid(path, pool)); /* Make sure something's there. */ SVN_ERR(svn_io_check_path(path, &kind, pool)); if (kind == svn_node_none) return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, _("'%s' not found"), svn_path_local_style(path, pool)); if (kind == svn_node_unknown) return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Unsupported node kind for path '%s'"), svn_path_local_style(path, pool)); /* Get the original entry for this path if one exists (perhaps this is actually a replacement of a previously deleted thing). Note that this is one of the few functions that is allowed to see 'deleted' entries; it's totally fine to have an entry that is scheduled for addition and still previously 'deleted'. */ SVN_ERR(svn_wc_adm_probe_try3(&adm_access, parent_access, path, TRUE, copyfrom_url != NULL ? -1 : 0, cancel_func, cancel_baton, pool)); if (adm_access) SVN_ERR(svn_wc_entry(&orig_entry, path, adm_access, TRUE, pool)); else orig_entry = NULL; /* You can only add something that is not in revision control, or that is slated for deletion from revision control, or has been previously 'deleted', unless, of course, you're specifying an addition with -history-; then it's okay for the object to be under version control already; it's not really new. */ if (orig_entry) { if ((! copyfrom_url) && (orig_entry->schedule != svn_wc_schedule_delete) && (! orig_entry->deleted)) { return svn_error_createf (SVN_ERR_ENTRY_EXISTS, NULL, _("'%s' is already under version control"), svn_path_local_style(path, pool)); } else if (orig_entry->kind != kind) { /* ### todo: At some point, we obviously don't want to block replacements where the node kind changes. When this happens, svn_wc_revert2() needs to learn how to revert this situation. At present we are using a specific node-change error so that clients can detect it. */ return svn_error_createf (SVN_ERR_WC_NODE_KIND_CHANGE, NULL, _("Can't replace '%s' with a node of a differing type; " "the deletion must be committed and the parent updated " "before adding '%s'"), svn_path_local_style(path, pool), svn_path_local_style(path, pool)); } if (orig_entry->schedule == svn_wc_schedule_delete) is_replace = TRUE; } /* Split off the base_name from the parent directory. */ svn_path_split(path, &parent_dir, &base_name, pool); SVN_ERR(svn_wc_entry(&parent_entry, parent_dir, parent_access, FALSE, pool)); if (! parent_entry) return svn_error_createf (SVN_ERR_ENTRY_NOT_FOUND, NULL, _("Can't find parent directory's entry while trying to add '%s'"), svn_path_local_style(path, pool)); if (parent_entry->schedule == svn_wc_schedule_delete) return svn_error_createf (SVN_ERR_WC_SCHEDULE_CONFLICT, NULL, _("Can't add '%s' to a parent directory scheduled for deletion"), svn_path_local_style(path, pool)); /* Init the modify flags. */ modify_flags = SVN_WC__ENTRY_MODIFY_SCHEDULE | SVN_WC__ENTRY_MODIFY_KIND; if (! (is_replace || copyfrom_url)) modify_flags |= SVN_WC__ENTRY_MODIFY_REVISION; /* If a copy ancestor was given, make sure the copyfrom URL is in the same repository (if possible) and put the proper ancestry info in the new entry */ if (copyfrom_url) { if (parent_entry->repos && ! svn_path_is_ancestor(parent_entry->repos, copyfrom_url)) return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("The URL '%s' has a different repository " "root than its parent"), copyfrom_url); tmp_entry.copyfrom_url = copyfrom_url; tmp_entry.copyfrom_rev = copyfrom_rev; tmp_entry.copied = TRUE; modify_flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_URL; modify_flags |= SVN_WC__ENTRY_MODIFY_COPYFROM_REV; modify_flags |= SVN_WC__ENTRY_MODIFY_COPIED; } /* If this is a replacement we want to remove the checksum so it is not set * to the old value. */ if (is_replace) { tmp_entry.checksum = NULL; modify_flags |= SVN_WC__ENTRY_MODIFY_CHECKSUM; } tmp_entry.revision = 0; tmp_entry.kind = kind; tmp_entry.schedule = svn_wc_schedule_add; /* Now, add the entry for this item to the parent_dir's entries file, marking it for addition. */ SVN_ERR(svn_wc__entry_modify(parent_access, base_name, &tmp_entry, modify_flags, TRUE, pool)); /* If this is a replacement without history, we need to reset the properties for PATH. */ if (orig_entry && (! copyfrom_url)) { const char *prop_path; SVN_ERR(svn_wc__prop_path(&prop_path, path, orig_entry->kind, FALSE, pool)); SVN_ERR(remove_file_if_present(prop_path, pool)); } if (kind == svn_node_dir) /* scheduling a directory for addition */ { if (! copyfrom_url) { const svn_wc_entry_t *p_entry; /* ### why not use parent_entry? */ const char *new_url; /* Get the entry for this directory's parent. We need to snatch the ancestor path out of there. */ SVN_ERR(svn_wc_entry(&p_entry, parent_dir, parent_access, FALSE, pool)); /* Derive the parent path for our new addition here. */ new_url = svn_path_url_add_component(p_entry->url, base_name, pool); /* Make sure this new directory has an admistrative subdirectory created inside of it */ SVN_ERR(svn_wc_ensure_adm2(path, NULL, new_url, p_entry->repos, 0, pool)); } else { /* When we are called with the copyfrom arguments set and with the admin directory already in existence, then the dir will contain the copyfrom settings. So we need to pass the copyfrom arguments to the ensure call. */ SVN_ERR(svn_wc_ensure_adm2(path, NULL, copyfrom_url, parent_entry->repos, copyfrom_rev, pool)); } /* We want the locks to persist, so use the access baton's pool */ if (! orig_entry || orig_entry->deleted) { apr_pool_t* access_pool = svn_wc_adm_access_pool(parent_access); SVN_ERR(svn_wc_adm_open3(&adm_access, parent_access, path, TRUE, copyfrom_url != NULL ? -1 : 0, cancel_func, cancel_baton, 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_adm2 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, parent_entry->repos, 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, NULL, TRUE, pool)); } } /* Report the addition to the caller. */ if (notify_func != NULL) { svn_wc_notify_t *notify = svn_wc_create_notify(path, svn_wc_notify_add, pool); notify->kind = kind; (*notify_func)(notify_baton, notify, pool); } return SVN_NO_ERROR;}svn_error_t *svn_wc_add(const char *path, svn_wc_adm_access_t *parent_access, const char *copyfrom_url, svn_revnum_t copyfrom_rev, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func_t notify_func, void *notify_baton, apr_pool_t *pool){ svn_wc__compat_notify_baton_t nb; nb.func = notify_func; nb.baton = notify_baton; return svn_wc_add2(path, parent_access, copyfrom_url, copyfrom_rev, cancel_func, cancel_baton, svn_wc__compat_call_notify_func, &nb, pool);}/* 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 necessarily 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. Sets *REVERTED to TRUE if something actually is reverted. Use SVN_WC_ENTRY_THIS_DIR as NAME for reverting ADM_ACCESS directory itself. Use POOL for any temporary allocations.*/static svn_error_t *revert_admin_things(svn_wc_adm_access_t *adm_access, const char *name, const svn_wc_entry_t *entry, svn_boolean_t *reverted, svn_boolean_t use_commit_times, apr_pool_t *pool){ const char *fullpath; /* If true, force reinstallation of working file. */ svn_boolean_t reinstall_working = FALSE; svn_wc_entry_t tmp_entry; apr_uint32_t flags = 0; svn_stringbuf_t *log_accum = svn_stringbuf_create("", pool); apr_hash_t *baseprops = NULL; const char *adm_path = svn_wc_adm_access_path(adm_access); /* Build the full path of the thing we're reverting. */ fullpath = svn_wc_adm_access_path(adm_access); if (strcmp(name, SVN_WC_ENTRY_THIS_DIR) != 0) fullpath = svn_path_join(fullpath, name, pool); /* Deal with properties. */ if (entry->schedule == svn_wc_schedule_replace) { const char *rprop; svn_node_kind_t kind; /* Use the revertpath as the new propsbase if it exists. */ SVN_ERR(svn_wc__prop_revert_path(&rprop, fullpath, entry->kind, FALSE, pool)); SVN_ERR(svn_io_check_path(rprop, &kind, pool)); if (kind == svn_node_file) { baseprops = apr_hash_make(pool); SVN_ERR(svn_wc__load_prop_file(rprop, baseprops, pool)); /* Ensure the revert propfile gets removed. */ SVN_ERR(svn_wc__loggy_remove (&log_accum, adm_access, svn_path_is_child(adm_path, rprop, pool), pool)); *reverted = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -