2 * iprops.c: wrappers around wc inherited property functionality
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
24 /* ==================================================================== */
30 #include "svn_error.h"
32 #include "svn_pools.h"
35 #include "svn_props.h"
39 #include "svn_private_config.h"
41 #include "private/svn_wc_private.h"
46 /* Determine if LOCAL_ABSPATH needs an inherited property cache. If it does,
47 then set *NEEDS_CACHE to TRUE, set it to FALSE otherwise. All other args
48 are as per svn_client__get_inheritable_props(). */
50 need_to_cache_iprops(svn_boolean_t *needs_cache,
51 const char *local_abspath,
52 svn_ra_session_t *ra_session,
53 svn_client_ctx_t *ctx,
54 apr_pool_t *scratch_pool)
56 svn_boolean_t is_wc_root;
57 svn_boolean_t is_switched;
60 err = svn_wc_check_root(&is_wc_root, &is_switched, NULL,
61 ctx->wc_ctx, local_abspath,
64 /* LOCAL_ABSPATH doesn't need a cache if it doesn't exist. */
67 if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
75 return svn_error_trace(err);
79 /* Starting assumption. */
82 if (is_wc_root || is_switched)
84 const char *session_url;
85 const char *session_root_url;
87 /* Looks likely that we need an inherited properties cache...Unless
88 LOCAL_ABSPATH is a WC root that points to the repos root. Then it
89 doesn't need a cache because it has nowhere to inherit from. Check
91 SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, scratch_pool));
92 SVN_ERR(svn_ra_get_repos_root2(ra_session, &session_root_url,
95 if (strcmp(session_root_url, session_url) != 0)
103 svn_client__iprop_relpaths_to_urls(apr_array_header_t *inherited_props,
104 const char *repos_root_url,
105 apr_pool_t *result_pool,
106 apr_pool_t *scratch_pool)
110 for (i = 0; i < inherited_props->nelts; i++)
112 svn_prop_inherited_item_t *elt =
113 APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
115 /* Convert repos root relpaths to full URLs. */
116 if (! (svn_path_is_url(elt->path_or_url)
117 || svn_dirent_is_absolute(elt->path_or_url)))
119 elt->path_or_url = svn_path_url_add_component2(repos_root_url,
127 /* The real implementation of svn_client__get_inheritable_props */
129 get_inheritable_props(apr_hash_t **wcroot_iprops,
130 const char *local_abspath,
131 svn_revnum_t revision,
133 svn_ra_session_t *ra_session,
134 svn_client_ctx_t *ctx,
135 apr_pool_t *result_pool,
136 apr_pool_t *scratch_pool)
138 apr_hash_t *iprop_paths;
139 apr_hash_index_t *hi;
140 apr_pool_t *iterpool = svn_pool_create(scratch_pool);
141 apr_pool_t *session_pool = NULL;
142 *wcroot_iprops = apr_hash_make(result_pool);
144 SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
146 /* If we don't have a base revision for LOCAL_ABSPATH then it can't
147 possibly be a working copy root, nor can it contain any WC roots
148 in the form of switched subtrees. So there is nothing to cache. */
150 SVN_ERR(svn_wc__get_cached_iprop_children(&iprop_paths, depth,
151 ctx->wc_ctx, local_abspath,
152 scratch_pool, iterpool));
154 /* If we are in the midst of a checkout or an update that is bringing in
155 an external, then svn_wc__get_cached_iprop_children won't return
156 LOCAL_ABSPATH in IPROPS_PATHS because the former has no cached iprops
157 yet. So make sure LOCAL_ABSPATH is present if it's a WC root. */
158 if (!svn_hash_gets(iprop_paths, local_abspath))
160 svn_boolean_t needs_cached_iprops;
162 SVN_ERR(need_to_cache_iprops(&needs_cached_iprops, local_abspath,
163 ra_session, ctx, iterpool));
164 if (needs_cached_iprops)
166 const char *target_abspath = apr_pstrdup(scratch_pool,
169 /* As value we set TARGET_ABSPATH, but any string besides ""
171 svn_hash_sets(iprop_paths, target_abspath, target_abspath);
175 for (hi = apr_hash_first(scratch_pool, iprop_paths);
177 hi = apr_hash_next(hi))
179 const char *child_abspath = apr_hash_this_key(hi);
180 const char *child_repos_relpath = apr_hash_this_val(hi);
182 apr_array_header_t *inherited_props;
185 svn_pool_clear(iterpool);
187 if (*child_repos_relpath == '\0')
189 /* A repository root doesn't have inherited properties */
193 SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, child_abspath,
194 iterpool, iterpool));
196 SVN_ERR(svn_ra_reparent(ra_session, url, scratch_pool));
200 session_pool = svn_pool_create(scratch_pool);
202 SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
204 session_pool, iterpool));
207 err = svn_ra_get_inherited_props(ra_session, &inherited_props,
209 result_pool, iterpool);
213 if (err->apr_err != SVN_ERR_FS_NOT_FOUND)
214 return svn_error_trace(err);
216 svn_error_clear(err);
220 svn_hash_sets(*wcroot_iprops,
221 apr_pstrdup(result_pool, child_abspath),
226 svn_pool_destroy(iterpool);
228 svn_pool_destroy(session_pool);
235 svn_client__get_inheritable_props(apr_hash_t **wcroot_iprops,
236 const char *local_abspath,
237 svn_revnum_t revision,
239 svn_ra_session_t *ra_session,
240 svn_client_ctx_t *ctx,
241 apr_pool_t *result_pool,
242 apr_pool_t *scratch_pool)
244 const char *old_session_url;
247 *wcroot_iprops = NULL;
249 if (!SVN_IS_VALID_REVNUM(revision))
253 SVN_ERR(svn_ra_get_session_url(ra_session, &old_session_url, scratch_pool));
255 /* We just wrap a simple helper function, as it is to easy to leave the ra
256 session rooted at some wrong path without a wrapper like this.
258 During development we had problems where some now deleted switched path
259 made the update try to update to that url instead of the intended url
262 err = get_inheritable_props(wcroot_iprops, local_abspath, revision, depth,
263 ra_session, ctx, result_pool, scratch_pool);
267 err = svn_error_compose_create(
269 svn_ra_reparent(ra_session, old_session_url, scratch_pool));
271 return svn_error_trace(err);