📄 lock.c
字号:
svn_boolean_t tree_lock, apr_pool_t *pool){ return svn_wc_adm_probe_open3(adm_access, associated, path, write_lock, (tree_lock ? -1 : 0), NULL, NULL, pool);}svn_error_t *svn_wc_adm_probe_open2(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, svn_boolean_t write_lock, int depth, apr_pool_t *pool){ return svn_wc_adm_probe_open3(adm_access, associated, path, write_lock, depth, NULL, NULL, pool);}svn_error_t *svn_wc_adm_probe_open3(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, svn_boolean_t write_lock, int depth, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool){ svn_error_t *err; const char *dir; int wc_format; SVN_ERR(probe(&dir, path, &wc_format, pool)); /* If we moved up a directory, then the path is not a directory, or it is not under version control. In either case, the notion of a depth does not apply to the provided path. Disable it so that we don't end up trying to lock more than we need. */ if (dir != path) depth = 0; err = svn_wc_adm_open3(adm_access, associated, dir, write_lock, depth, cancel_func, cancel_baton, pool); if (err) { svn_error_t *err2; /* If we got an error on the parent dir, that means we failed to get an access baton for the child in the first place. And if the reason we couldn't get the child access baton is that the child is not a versioned directory, then return an error about the child, not the parent. */ svn_node_kind_t child_kind; if ((err2 = svn_io_check_path(path, &child_kind, pool))) { svn_error_compose(err, err2); return err; } if ((dir != path) && (child_kind == svn_node_dir) && (err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)) { svn_error_clear(err); return svn_error_createf(SVN_ERR_WC_NOT_DIRECTORY, NULL, _("'%s' is not a working copy"), svn_path_local_style(path, pool)); } else { return err; } } if (wc_format && ! (*adm_access)->wc_format) (*adm_access)->wc_format = wc_format; return SVN_NO_ERROR;}svn_error_t *svn_wc__adm_retrieve_internal(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, apr_pool_t *pool){ if (associated->set) *adm_access = apr_hash_get(associated->set, path, APR_HASH_KEY_STRING); else if (! strcmp(associated->path, path)) *adm_access = associated; else *adm_access = NULL; if (*adm_access == &missing) *adm_access = NULL; return SVN_NO_ERROR;}svn_error_t *svn_wc_adm_retrieve(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, apr_pool_t *pool){ SVN_ERR(svn_wc__adm_retrieve_internal(adm_access, associated, path, pool)); /* Most of the code expects access batons to exist, so returning an error generally makes the calling code simpler as it doesn't need to check for NULL batons. */ if (! *adm_access) { const char *wcpath; const svn_wc_entry_t *subdir_entry; svn_node_kind_t wckind; svn_node_kind_t kind; svn_error_t *err; err = svn_wc_entry(&subdir_entry, path, associated, TRUE, pool); /* If we can't get an entry here, we are in pretty bad shape, and will have to fall back to using just regular old paths to see what's going on. */ if (err) { svn_error_clear(err); subdir_entry = NULL; } err = svn_io_check_path(path, &kind, pool); /* If we can't check the path, we can't make a good error message. */ if (err) { return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, err, _("Unable to check path existence for '%s'"), svn_path_local_style(path, pool)); } if (subdir_entry) { if (subdir_entry->kind == svn_node_dir && kind == svn_node_file) { return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("Expected '%s' to be a directory but found a file"), svn_path_local_style(path, pool)); } else if (subdir_entry->kind == svn_node_file && kind == svn_node_dir) { return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("Expected '%s' to be a file but found a directory"), svn_path_local_style(path, pool)); } } wcpath = svn_wc__adm_path(path, FALSE, pool, NULL); err = svn_io_check_path(wcpath, &wckind, pool); /* If we can't check the path, we can't make a good error message. */ if (err) { return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, err, _("Unable to check path existence for '%s'"), svn_path_local_style(wcpath, pool)); } if (kind == svn_node_none) return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("Directory '%s' is missing"), svn_path_local_style(path, pool)); else if (kind == svn_node_dir && wckind == svn_node_none) return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("Directory '%s' containing working copy admin area is missing"), svn_path_local_style(wcpath, pool)); else if (kind == svn_node_dir && wckind == svn_node_dir) return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("Unable to lock '%s'"), svn_path_local_style(path, pool)); /* If all else fails, return our useless generic error. */ return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("Working copy '%s' is not locked"), svn_path_local_style(path, pool)); } return SVN_NO_ERROR;}svn_error_t *svn_wc_adm_probe_retrieve(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, apr_pool_t *pool){ const char *dir; int wc_format; SVN_ERR(probe(&dir, path, &wc_format, pool)); SVN_ERR(svn_wc_adm_retrieve(adm_access, associated, dir, pool)); if (wc_format && ! (*adm_access)->wc_format) (*adm_access)->wc_format = wc_format; return SVN_NO_ERROR;}/* To preserve API compatibility with Subversion 1.0.0 */svn_error_t *svn_wc_adm_probe_try(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, svn_boolean_t write_lock, svn_boolean_t tree_lock, apr_pool_t *pool){ return svn_wc_adm_probe_try3(adm_access, associated, path, write_lock, (tree_lock ? -1 : 0), NULL, NULL, pool);}svn_error_t *svn_wc_adm_probe_try2(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, svn_boolean_t write_lock, int depth, apr_pool_t *pool){ return svn_wc_adm_probe_try3(adm_access, associated, path, write_lock, depth, NULL, NULL, pool);}svn_error_t *svn_wc_adm_probe_try3(svn_wc_adm_access_t **adm_access, svn_wc_adm_access_t *associated, const char *path, svn_boolean_t write_lock, int depth, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool){ svn_error_t *err; err = svn_wc_adm_probe_retrieve(adm_access, associated, path, pool); /* SVN_ERR_WC_NOT_LOCKED would mean there was no access baton for path in associated, in which case we want to open an access baton and add it to associated. */ if (err && (err->apr_err == SVN_ERR_WC_NOT_LOCKED)) { svn_error_clear(err); err = svn_wc_adm_probe_open3(adm_access, associated, path, write_lock, depth, cancel_func, cancel_baton, svn_wc_adm_access_pool(associated)); /* If the path is not a versioned directory, we just return a null access baton with no error. Note that of the errors we do report, the most important (and probably most likely) is SVN_ERR_WC_LOCKED. That error would mean that someone else has this area locked, and we definitely want to bail in that case. */ if (err && (err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)) { svn_error_clear(err); *adm_access = NULL; err = NULL; } } return err;}/* A helper for svn_wc_adm_open_anchor. Add all the access batons in the T_ACCESS set, including T_ACCESS, to the P_ACCESS set. */static void join_batons(svn_wc_adm_access_t *p_access, svn_wc_adm_access_t *t_access, apr_pool_t *pool){ apr_hash_index_t *hi; adm_ensure_set(p_access); if (! t_access->set) { t_access->set = p_access->set; apr_hash_set(p_access->set, t_access->path, APR_HASH_KEY_STRING, t_access); return; } for (hi = apr_hash_first(pool, t_access->set); hi; hi = apr_hash_next(hi)) { const void *key; void *val; svn_wc_adm_access_t *adm_access; apr_hash_this(hi, &key, NULL, &val); adm_access = val; if (adm_access != &missing) adm_access->set = p_access->set; apr_hash_set(p_access->set, key, APR_HASH_KEY_STRING, adm_access); } t_access->set_owner = FALSE;}svn_error_t *svn_wc_adm_open_anchor(svn_wc_adm_access_t **anchor_access, svn_wc_adm_access_t **target_access, const char **target, const char *path, svn_boolean_t write_lock, int depth, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool){ const char *base_name = svn_path_basename(path, pool); if (svn_path_is_empty(path) || ! strcmp(path, "/") || ! strcmp(base_name, "..")) { SVN_ERR(do_open(anchor_access, NULL, path, write_lock, depth, FALSE, cancel_func, cancel_baton, pool)); *target_access = *anchor_access; *target = ""; } else { svn_error_t *err; svn_wc_adm_access_t *p_access, *t_access; const char *parent = svn_path_dirname(path, pool); svn_error_t *p_access_err = SVN_NO_ERROR; /* Try to open parent of PATH to setup P_ACCESS */ err = do_open(&p_access, NULL, parent, write_lock, 0, FALSE, cancel_func, cancel_baton, pool); if (err) { if (err->apr_err == SVN_ERR_WC_NOT_DIRECTORY) { svn_error_clear(err); p_access = NULL; } else if (write_lock && (err->apr_err == SVN_ERR_WC_LOCKED || APR_STATUS_IS_EACCES(err->apr_err))) { /* If P_ACCESS isn't to be returned then a read-only baton will do for now, but keep the error in case we need it. */ svn_error_t *err2 = do_open(&p_access, NULL, parent, FALSE, 0, FALSE, cancel_func, cancel_baton, pool); if (err2) { svn_error_clear(err2); return err; } p_access_err = err; } else return err; } /* Try to open PATH to setup T_ACCESS */ err = do_open(&t_access, NULL, path, write_lock, depth, FALSE, cancel_func, cancel_baton, pool); if (err) { if (! p_access || err->apr_err != SVN_ERR_WC_NOT_DIRECTORY) { if (p_access) svn_error_clear(do_close(p_access, FALSE, TRUE)); svn_error_clear(p_access_err); return err; } svn_error_clear(err); t_access = NULL; } /* At this stage might have P_ACCESS, T_ACCESS or both */ /* Check for switched or disjoint P_ACCESS and T_ACCESS */ if (p_access && t_access)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -