TortoiseGitMerge: Updated libsvn stuff
[TortoiseGit.git] / src / TortoiseMerge / libsvn_diff / properties.c
bloba97a03bca04b2771629a885edc0d7a598319083d
1 /*
2 * properties.c: stuff related to Subversion properties
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
20 * under the License.
21 * ====================================================================
26 #include <apr_pools.h>
27 #include <apr_hash.h>
28 #include <apr_tables.h>
29 #include <string.h> /* for strncmp() */
30 #include "svn_hash.h"
31 #include "svn_string.h"
32 #include "svn_props.h"
33 #include "svn_error.h"
34 #include "svn_ctype.h"
35 #include "private/svn_subr_private.h"
38 /* All Subversion-specific versioned node properties
39 * known to this client, that are applicable to both a file and a dir.
41 #define SVN_PROP__NODE_COMMON_PROPS SVN_PROP_MERGEINFO, \
42 SVN_PROP_TEXT_TIME, \
43 SVN_PROP_OWNER, \
44 SVN_PROP_GROUP, \
45 SVN_PROP_UNIX_MODE,
47 /* All Subversion-specific versioned node properties
48 * known to this client, that are applicable to a dir only.
50 #define SVN_PROP__NODE_DIR_ONLY_PROPS SVN_PROP_IGNORE, \
51 SVN_PROP_INHERITABLE_IGNORES, \
52 SVN_PROP_INHERITABLE_AUTO_PROPS, \
53 SVN_PROP_EXTERNALS,
55 /* All Subversion-specific versioned node properties
56 * known to this client, that are applicable to a file only.
58 #define SVN_PROP__NODE_FILE_ONLY_PROPS SVN_PROP_MIME_TYPE, \
59 SVN_PROP_EOL_STYLE, \
60 SVN_PROP_KEYWORDS, \
61 SVN_PROP_EXECUTABLE, \
62 SVN_PROP_NEEDS_LOCK, \
63 SVN_PROP_SPECIAL,
65 static const char *const known_rev_props[]
66 = { SVN_PROP_REVISION_ALL_PROPS
67 NULL };
69 static const char *const known_node_props[]
70 = { SVN_PROP__NODE_COMMON_PROPS
71 SVN_PROP__NODE_DIR_ONLY_PROPS
72 SVN_PROP__NODE_FILE_ONLY_PROPS
73 NULL };
75 static const char *const known_dir_props[]
76 = { SVN_PROP__NODE_COMMON_PROPS
77 SVN_PROP__NODE_DIR_ONLY_PROPS
78 NULL };
80 static const char *const known_file_props[]
81 = { SVN_PROP__NODE_COMMON_PROPS
82 SVN_PROP__NODE_FILE_ONLY_PROPS
83 NULL };
85 static svn_boolean_t
86 is_known_prop(const char *prop_name,
87 const char *const *known_props)
89 while (*known_props)
91 if (strcmp(prop_name, *known_props++) == 0)
92 return TRUE;
94 return FALSE;
97 svn_boolean_t
98 svn_prop_is_known_svn_rev_prop(const char *prop_name)
100 return is_known_prop(prop_name, known_rev_props);
103 svn_boolean_t
104 svn_prop_is_known_svn_node_prop(const char *prop_name)
106 return is_known_prop(prop_name, known_node_props);
109 svn_boolean_t
110 svn_prop_is_known_svn_file_prop(const char *prop_name)
112 return is_known_prop(prop_name, known_file_props);
115 svn_boolean_t
116 svn_prop_is_known_svn_dir_prop(const char *prop_name)
118 return is_known_prop(prop_name, known_dir_props);
122 svn_boolean_t
123 svn_prop_is_svn_prop(const char *prop_name)
125 return strncmp(prop_name, SVN_PROP_PREFIX, (sizeof(SVN_PROP_PREFIX) - 1))
126 == 0;
130 svn_boolean_t
131 svn_prop_has_svn_prop(const apr_hash_t *props, apr_pool_t *pool)
133 apr_hash_index_t *hi;
134 const void *prop_name;
136 if (! props)
137 return FALSE;
139 for (hi = apr_hash_first(pool, (apr_hash_t *)props); hi;
140 hi = apr_hash_next(hi))
142 apr_hash_this(hi, &prop_name, NULL, NULL);
143 if (svn_prop_is_svn_prop((const char *) prop_name))
144 return TRUE;
147 return FALSE;
151 #define SIZEOF_WC_PREFIX (sizeof(SVN_PROP_WC_PREFIX) - 1)
152 #define SIZEOF_ENTRY_PREFIX (sizeof(SVN_PROP_ENTRY_PREFIX) - 1)
154 svn_prop_kind_t
155 svn_property_kind2(const char *prop_name)
158 if (strncmp(prop_name, SVN_PROP_WC_PREFIX, SIZEOF_WC_PREFIX) == 0)
159 return svn_prop_wc_kind;
161 if (strncmp(prop_name, SVN_PROP_ENTRY_PREFIX, SIZEOF_ENTRY_PREFIX) == 0)
162 return svn_prop_entry_kind;
164 return svn_prop_regular_kind;
168 /* NOTE: this function is deprecated, but we cannot move it to deprecated.c
169 because we need the SIZEOF_*_PREFIX constant symbols defined above. */
170 svn_prop_kind_t
171 svn_property_kind(int *prefix_len,
172 const char *prop_name)
174 svn_prop_kind_t kind = svn_property_kind2(prop_name);
176 if (prefix_len)
178 if (kind == svn_prop_wc_kind)
179 *prefix_len = SIZEOF_WC_PREFIX;
180 else if (kind == svn_prop_entry_kind)
181 *prefix_len = SIZEOF_ENTRY_PREFIX;
182 else
183 *prefix_len = 0;
186 return kind;
190 svn_error_t *
191 svn_categorize_props(const apr_array_header_t *proplist,
192 apr_array_header_t **entry_props,
193 apr_array_header_t **wc_props,
194 apr_array_header_t **regular_props,
195 apr_pool_t *pool)
197 int i;
198 if (entry_props)
199 *entry_props = apr_array_make(pool, 1, sizeof(svn_prop_t));
200 if (wc_props)
201 *wc_props = apr_array_make(pool, 1, sizeof(svn_prop_t));
202 if (regular_props)
203 *regular_props = apr_array_make(pool, 1, sizeof(svn_prop_t));
205 for (i = 0; i < proplist->nelts; i++)
207 svn_prop_t *prop, *newprop;
208 enum svn_prop_kind kind;
210 prop = &APR_ARRAY_IDX(proplist, i, svn_prop_t);
211 kind = svn_property_kind2(prop->name);
212 newprop = NULL;
214 if (kind == svn_prop_regular_kind)
216 if (regular_props)
217 newprop = apr_array_push(*regular_props);
219 else if (kind == svn_prop_wc_kind)
221 if (wc_props)
222 newprop = apr_array_push(*wc_props);
224 else if (kind == svn_prop_entry_kind)
226 if (entry_props)
227 newprop = apr_array_push(*entry_props);
229 else
230 /* Technically this can't happen, but might as well have the
231 code ready in case that ever changes. */
232 return svn_error_createf(SVN_ERR_BAD_PROP_KIND, NULL,
233 "Bad property kind for property '%s'",
234 prop->name);
236 if (newprop)
238 newprop->name = prop->name;
239 newprop->value = prop->value;
243 return SVN_NO_ERROR;
247 svn_error_t *
248 svn_prop_diffs(apr_array_header_t **propdiffs,
249 const apr_hash_t *target_props,
250 const apr_hash_t *source_props,
251 apr_pool_t *pool)
253 apr_hash_index_t *hi;
254 apr_array_header_t *ary = apr_array_make(pool, 1, sizeof(svn_prop_t));
256 /* Note: we will be storing the pointers to the keys (from the hashes)
257 into the propdiffs array. It is acceptable for us to
258 reference the same memory as the base/target_props hash. */
260 /* Loop over SOURCE_PROPS and examine each key. This will allow us to
261 detect any `deletion' events or `set-modification' events. */
262 for (hi = apr_hash_first(pool, (apr_hash_t *)source_props); hi;
263 hi = apr_hash_next(hi))
265 const void *key;
266 apr_ssize_t klen;
267 void *val;
268 const svn_string_t *propval1, *propval2;
270 /* Get next property */
271 apr_hash_this(hi, &key, &klen, &val);
272 propval1 = val;
274 /* Does property name exist in TARGET_PROPS? */
275 propval2 = apr_hash_get((apr_hash_t *)target_props, key, klen);
277 if (propval2 == NULL)
279 /* Add a delete event to the array */
280 svn_prop_t *p = apr_array_push(ary);
281 p->name = key;
282 p->value = NULL;
284 else if (! svn_string_compare(propval1, propval2))
286 /* Add a set (modification) event to the array */
287 svn_prop_t *p = apr_array_push(ary);
288 p->name = key;
289 p->value = svn_string_dup(propval2, pool);
293 /* Loop over TARGET_PROPS and examine each key. This allows us to
294 detect `set-creation' events */
295 for (hi = apr_hash_first(pool, (apr_hash_t *)target_props); hi;
296 hi = apr_hash_next(hi))
298 const void *key;
299 apr_ssize_t klen;
300 void *val;
301 const svn_string_t *propval;
303 /* Get next property */
304 apr_hash_this(hi, &key, &klen, &val);
305 propval = val;
307 /* Does property name exist in SOURCE_PROPS? */
308 if (NULL == apr_hash_get((apr_hash_t *)source_props, key, klen))
310 /* Add a set (creation) event to the array */
311 svn_prop_t *p = apr_array_push(ary);
312 p->name = key;
313 p->value = svn_string_dup(propval, pool);
317 /* Done building our array of user events. */
318 *propdiffs = ary;
320 return SVN_NO_ERROR;
323 apr_hash_t *
324 svn_prop__patch(const apr_hash_t *original_props,
325 const apr_array_header_t *prop_changes,
326 apr_pool_t *pool)
328 apr_hash_t *props = apr_hash_copy(pool, original_props);
329 int i;
331 for (i = 0; i < prop_changes->nelts; i++)
333 const svn_prop_t *p = &APR_ARRAY_IDX(prop_changes, i, svn_prop_t);
335 svn_hash_sets(props, p->name, p->value);
337 return props;
341 * Reallocate the members of PROP using POOL.
343 static void
344 svn_prop__members_dup(svn_prop_t *prop, apr_pool_t *pool)
346 if (prop->name)
347 prop->name = apr_pstrdup(pool, prop->name);
348 if (prop->value)
349 prop->value = svn_string_dup(prop->value, pool);
352 svn_prop_t *
353 svn_prop_dup(const svn_prop_t *prop, apr_pool_t *pool)
355 svn_prop_t *new_prop = apr_palloc(pool, sizeof(*new_prop));
357 *new_prop = *prop;
359 svn_prop__members_dup(new_prop, pool);
361 return new_prop;
364 apr_array_header_t *
365 svn_prop_array_dup(const apr_array_header_t *array, apr_pool_t *pool)
367 int i;
368 apr_array_header_t *new_array = apr_array_copy(pool, array);
369 for (i = 0; i < new_array->nelts; ++i)
371 svn_prop_t *elt = &APR_ARRAY_IDX(new_array, i, svn_prop_t);
372 svn_prop__members_dup(elt, pool);
374 return new_array;
377 apr_array_header_t *
378 svn_prop_hash_to_array(const apr_hash_t *hash,
379 apr_pool_t *pool)
381 apr_hash_index_t *hi;
382 apr_array_header_t *array = apr_array_make(pool,
383 apr_hash_count((apr_hash_t *)hash),
384 sizeof(svn_prop_t));
386 for (hi = apr_hash_first(pool, (apr_hash_t *)hash); hi;
387 hi = apr_hash_next(hi))
389 const void *key;
390 void *val;
391 svn_prop_t prop;
393 apr_hash_this(hi, &key, NULL, &val);
394 prop.name = key;
395 prop.value = val;
396 APR_ARRAY_PUSH(array, svn_prop_t) = prop;
399 return array;
402 apr_hash_t *
403 svn_prop_hash_dup(const apr_hash_t *hash,
404 apr_pool_t *pool)
406 apr_hash_index_t *hi;
407 apr_hash_t *new_hash = apr_hash_make(pool);
409 for (hi = apr_hash_first(pool, (apr_hash_t *)hash); hi;
410 hi = apr_hash_next(hi))
412 const void *key;
413 apr_ssize_t klen;
414 void *prop;
416 apr_hash_this(hi, &key, &klen, &prop);
417 apr_hash_set(new_hash, apr_pstrmemdup(pool, key, klen), klen,
418 svn_string_dup(prop, pool));
420 return new_hash;
423 apr_hash_t *
424 svn_prop_array_to_hash(const apr_array_header_t *properties,
425 apr_pool_t *pool)
427 int i;
428 apr_hash_t *prop_hash = apr_hash_make(pool);
430 for (i = 0; i < properties->nelts; i++)
432 const svn_prop_t *prop = &APR_ARRAY_IDX(properties, i, svn_prop_t);
433 svn_hash_sets(prop_hash, prop->name, prop->value);
436 return prop_hash;
439 svn_boolean_t
440 svn_prop_is_boolean(const char *prop_name)
442 /* If we end up with more than 3 of these, we should probably put
443 them in a table and use bsearch. With only three, it doesn't
444 make any speed difference. */
445 if (strcmp(prop_name, SVN_PROP_EXECUTABLE) == 0
446 || strcmp(prop_name, SVN_PROP_NEEDS_LOCK) == 0
447 || strcmp(prop_name, SVN_PROP_SPECIAL) == 0)
448 return TRUE;
449 return FALSE;
453 svn_boolean_t
454 svn_prop_needs_translation(const char *propname)
456 /* ### Someday, we may want to be picky and choosy about which
457 properties require UTF8 and EOL conversion. For now, all "svn:"
458 props need it. */
460 return svn_prop_is_svn_prop(propname);
464 svn_boolean_t
465 svn_prop_name_is_valid(const char *prop_name)
467 const char *p = prop_name;
469 /* The characters we allow use identical representations in UTF8
470 and ASCII, so we can just test for the appropriate ASCII codes.
471 But we can't use standard C character notation ('A', 'B', etc)
472 because there's no guarantee that this C environment is using
473 ASCII. */
475 if (!(svn_ctype_isalpha(*p)
476 || *p == SVN_CTYPE_ASCII_COLON
477 || *p == SVN_CTYPE_ASCII_UNDERSCORE))
478 return FALSE;
479 p++;
480 for (; *p; p++)
482 if (!(svn_ctype_isalnum(*p)
483 || *p == SVN_CTYPE_ASCII_MINUS
484 || *p == SVN_CTYPE_ASCII_DOT
485 || *p == SVN_CTYPE_ASCII_COLON
486 || *p == SVN_CTYPE_ASCII_UNDERSCORE))
487 return FALSE;
489 return TRUE;
492 const char *
493 svn_prop_get_value(const apr_hash_t *props,
494 const char *prop_name)
496 svn_string_t *str;
498 if (!props)
499 return NULL;
501 str = svn_hash_gets((apr_hash_t *)props, prop_name);
503 if (str)
504 return str->data;
506 return NULL;