📄 prop_commands.c
字号:
* Allocate the item itself in POOL; set item->node_name to an * 'svn_stringbuf_t *' created from PATH and also allocated in POOL, * and set item->prop_hash to PROP_HASH. * * If PROP_HASH is null or has zero count, do nothing. */static voidpush_props_on_list(apr_array_header_t *list, apr_hash_t *prop_hash, const char *path, apr_pool_t *pool){ if (prop_hash && apr_hash_count(prop_hash)) { svn_client_proplist_item_t *item = apr_palloc(pool, sizeof(svn_client_proplist_item_t)); item->node_name = svn_stringbuf_create(path, pool); item->prop_hash = prop_hash; *((svn_client_proplist_item_t **) apr_array_push(list)) = item; }}/* Helper for the remote case of svn_client_proplist. * * Push a new 'svn_client_proplist_item_t *' item onto PROPLIST, * containing the properties for "TARGET_PREFIX/TARGET_RELATIVE" in * REVNUM, obtained using RA_LIB and SESSION. The item->node_name * will be "TARGET_PREFIX/TARGET_RELATIVE", and the value will be a * hash mapping 'const char *' property names onto 'svn_string_t *' * property values. * * Allocate the new item and its contents in POOL. * Do all looping, recursion, and temporary work in SCRATCHPOOL. * * KIND is the kind of the node at "TARGET_PREFIX/TARGET_RELATIVE". * * If RECURSE is true and KIND is svn_node_dir, then recurse. */static svn_error_t *remote_proplist(apr_array_header_t *proplist, const char *target_prefix, const char *target_relative, svn_node_kind_t kind, svn_revnum_t revnum, svn_ra_session_t *ra_session, svn_boolean_t recurse, apr_pool_t *pool, apr_pool_t *scratchpool){ apr_hash_t *dirents; apr_hash_t *prop_hash, *final_hash; apr_hash_index_t *hi; if (kind == svn_node_dir) { SVN_ERR(svn_ra_get_dir2(ra_session, (recurse ? &dirents : NULL), NULL, &prop_hash, target_relative, revnum, SVN_DIRENT_KIND, scratchpool)); } else if (kind == svn_node_file) { SVN_ERR(svn_ra_get_file(ra_session, target_relative, revnum, NULL, NULL, &prop_hash, scratchpool)); } else { return svn_error_createf (SVN_ERR_NODE_UNKNOWN_KIND, NULL, _("Unknown node kind for '%s'"), svn_path_join(target_prefix, target_relative, pool)); } /* Filter out non-regular properties, since the RA layer returns all kinds. Copy regular properties keys/vals from the prop_hash allocated in SCRATCHPOOL to the "final" hash allocated in POOL. */ final_hash = apr_hash_make(pool); for (hi = apr_hash_first(scratchpool, prop_hash); hi; hi = apr_hash_next(hi)) { const void *key; apr_ssize_t klen; void *val; svn_prop_kind_t prop_kind; const char *name; svn_string_t *value; apr_hash_this(hi, &key, &klen, &val); prop_kind = svn_property_kind(NULL, (const char *) key); if (prop_kind == svn_prop_regular_kind) { name = apr_pstrdup(pool, (const char *) key); value = svn_string_dup((svn_string_t *) val, pool); apr_hash_set(final_hash, name, klen, value); } } push_props_on_list(proplist, final_hash, svn_path_join(target_prefix, target_relative, scratchpool), pool); if (recurse && (kind == svn_node_dir) && (apr_hash_count(dirents) > 0)) { apr_pool_t *subpool = svn_pool_create(scratchpool); for (hi = apr_hash_first(scratchpool, dirents); hi; hi = apr_hash_next(hi)) { const void *key; void *val; const char *this_name; svn_dirent_t *this_ent; const char *new_target_relative; svn_pool_clear(subpool); apr_hash_this(hi, &key, NULL, &val); this_name = key; this_ent = val; new_target_relative = svn_path_join(target_relative, this_name, subpool); SVN_ERR(remote_proplist(proplist, target_prefix, new_target_relative, this_ent->kind, revnum, ra_session, recurse, pool, subpool)); } svn_pool_destroy(subpool); } return SVN_NO_ERROR;}/* Push an 'svn_client_proplist_item_t *' item onto PROP_LIST, where * item->node_name is an 'svn_stringbuf_t *' created from NODE_NAME, * and item->prop_hash is the property hash for NODE_NAME. * * If PRISTINE is true, get base props, else get working props. * * Allocate the item and its contents in POOL. */static svn_error_t *add_to_proplist(apr_array_header_t *prop_list, const char *node_name, svn_wc_adm_access_t *adm_access, svn_boolean_t pristine, apr_pool_t *pool){ apr_hash_t *hash; SVN_ERR(pristine_or_working_props(&hash, node_name, adm_access, pristine, pool)); push_props_on_list(prop_list, hash, node_name, pool); return SVN_NO_ERROR;}/* A baton for proplist_walk_cb. */struct proplist_walk_baton{ svn_boolean_t pristine; /* Select base rather than working props. */ svn_wc_adm_access_t *base_access; /* Access for the tree being walked. */ apr_array_header_t *props; /* Out: array of svn_client_proplist_item_t. */};/* An entries-walk callback for svn_client_proplist. * * For the path given by PATH and ENTRY, * populate wb->PROPS with a svn_client_proplist_item_t for each path, * where "wb" is the WALK_BATON of type "struct proplist_walk_baton *". * If wb->PRISTINE is true, use the base values, else use the working values. */static svn_error_t *proplist_walk_cb(const char *path, const svn_wc_entry_t *entry, void *walk_baton, apr_pool_t *pool){ struct proplist_walk_baton *wb = walk_baton; /* We're going to receive dirents twice; we want to ignore the first one (where it's a child of a parent dir), and only use the second one (where we're looking at THIS_DIR). */ if ((entry->kind == svn_node_dir) && (strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR) != 0)) return SVN_NO_ERROR; /* Ignore the entry if it does not exist at the time of interest. */ if (entry->schedule == (wb->pristine ? svn_wc_schedule_add : svn_wc_schedule_delete)) return SVN_NO_ERROR; path = apr_pstrdup(wb->props->pool, path); SVN_ERR(add_to_proplist(wb->props, path, wb->base_access, wb->pristine, wb->props->pool)); return SVN_NO_ERROR;}/* Note: this implementation is very similar to svn_client_propget. */svn_error_t *svn_client_proplist2(apr_array_header_t **props, const char *target, const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, svn_boolean_t recurse, svn_client_ctx_t *ctx, apr_pool_t *pool){ svn_wc_adm_access_t *adm_access; const svn_wc_entry_t *node; const char *utarget; /* target, or the url for target */ const char *url; svn_revnum_t revnum; *props = apr_array_make(pool, 5, sizeof(svn_client_proplist_item_t *)); SVN_ERR(maybe_convert_to_url(&utarget, target, revision, pool)); /* Iff utarget is a url, that means we must use it, that is, the requested property information is not available locally. */ if (svn_path_is_url(utarget)) { svn_ra_session_t *ra_session; svn_node_kind_t kind; /* Get an RA session for this URL. */ SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum, &url, target, peg_revision, revision, ctx, pool)); SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool)); SVN_ERR(remote_proplist(*props, url, "", kind, revnum, ra_session, recurse, pool, svn_pool_create(pool))); } else /* working copy path */ { svn_boolean_t pristine; SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, target, FALSE, recurse ? -1 : 0, ctx->cancel_func, ctx->cancel_baton, pool)); SVN_ERR(svn_wc_entry(&node, target, adm_access, FALSE, pool)); if (! node) return svn_error_createf (SVN_ERR_UNVERSIONED_RESOURCE, NULL, _("'%s' is not under version control"), svn_path_local_style(target, pool)); SVN_ERR(svn_client__get_revision_number (&revnum, NULL, revision, target, pool)); if ((revision->kind == svn_opt_revision_committed) || (revision->kind == svn_opt_revision_base)) { pristine = TRUE; } else /* must be the working revision */ { pristine = FALSE; } /* Fetch, recursively or not. */ if (recurse && (node->kind == svn_node_dir)) { static const svn_wc_entry_callbacks_t walk_callbacks = { proplist_walk_cb }; struct proplist_walk_baton wb; wb.base_access = adm_access; wb.props = *props; wb.pristine = pristine; SVN_ERR(svn_wc_walk_entries2(target, adm_access, &walk_callbacks, &wb, FALSE, ctx->cancel_func, ctx->cancel_baton, pool)); } else SVN_ERR(add_to_proplist(*props, target, adm_access, pristine, pool)); SVN_ERR(svn_wc_adm_close(adm_access)); } return SVN_NO_ERROR;}svn_error_t *svn_client_proplist(apr_array_header_t **props, const char *target, const svn_opt_revision_t *revision, svn_boolean_t recurse, svn_client_ctx_t *ctx, apr_pool_t *pool){ return svn_client_proplist2(props, target, revision, revision, recurse, ctx, pool);}svn_error_t *svn_client_revprop_list(apr_hash_t **props, const char *URL, const svn_opt_revision_t *revision, svn_revnum_t *set_rev, svn_client_ctx_t *ctx, apr_pool_t *pool){ svn_ra_session_t *ra_session; apr_hash_t *proplist; /* Open an RA session for the URL. Note that we don't have a local directory, nor a place to put temp files. */ SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL, NULL, NULL, NULL, FALSE, TRUE, ctx, pool)); /* Resolve the revision into something real, and return that to the caller as well. */ SVN_ERR(svn_client__get_revision_number (set_rev, ra_session, revision, NULL, pool)); /* The actual RA call. */ SVN_ERR(svn_ra_rev_proplist(ra_session, *set_rev, &proplist, pool)); *props = proplist; return SVN_NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -