2 * properties.c: stuff related to Subversion properties
4 * ====================================================================
5 * Copyright (c) 2000-2006 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #include <apr_pools.h>
23 #include <apr_tables.h>
24 #include <string.h> /* for strncmp() */
26 #include "svn_string.h"
27 #include "svn_props.h"
28 #include "svn_error.h"
29 #include "svn_ctype.h"
33 svn_prop_is_svn_prop(const char *prop_name
)
35 return strncmp(prop_name
, SVN_PROP_PREFIX
, (sizeof(SVN_PROP_PREFIX
) - 1))
42 svn_prop_has_svn_prop(apr_hash_t
*props
, apr_pool_t
*pool
)
45 const void *prop_name
;
50 for (hi
= apr_hash_first(pool
, props
); hi
; hi
= apr_hash_next(hi
))
52 apr_hash_this(hi
, &prop_name
, NULL
, NULL
);
53 if (svn_prop_is_svn_prop((const char *) prop_name
))
62 svn_property_kind(int *prefix_len
,
63 const char *prop_name
)
65 apr_size_t wc_prefix_len
= sizeof(SVN_PROP_WC_PREFIX
) - 1;
66 apr_size_t entry_prefix_len
= sizeof(SVN_PROP_ENTRY_PREFIX
) - 1;
68 if (strncmp(prop_name
, SVN_PROP_WC_PREFIX
, wc_prefix_len
) == 0)
71 *prefix_len
= wc_prefix_len
;
72 return svn_prop_wc_kind
;
75 if (strncmp(prop_name
, SVN_PROP_ENTRY_PREFIX
, entry_prefix_len
) == 0)
78 *prefix_len
= entry_prefix_len
;
79 return svn_prop_entry_kind
;
85 return svn_prop_regular_kind
;
90 svn_categorize_props(const apr_array_header_t
*proplist
,
91 apr_array_header_t
**entry_props
,
92 apr_array_header_t
**wc_props
,
93 apr_array_header_t
**regular_props
,
98 *entry_props
= apr_array_make(pool
, 1, sizeof(svn_prop_t
));
100 *wc_props
= apr_array_make(pool
, 1, sizeof(svn_prop_t
));
102 *regular_props
= apr_array_make(pool
, 1, sizeof(svn_prop_t
));
104 for (i
= 0; i
< proplist
->nelts
; i
++)
106 svn_prop_t
*prop
, *newprop
;
107 enum svn_prop_kind kind
;
109 prop
= &APR_ARRAY_IDX(proplist
, i
, svn_prop_t
);
110 kind
= svn_property_kind(NULL
, prop
->name
);
113 if (kind
== svn_prop_regular_kind
)
116 newprop
= apr_array_push(*regular_props
);
118 else if (kind
== svn_prop_wc_kind
)
121 newprop
= apr_array_push(*wc_props
);
123 else if (kind
== svn_prop_entry_kind
)
126 newprop
= apr_array_push(*entry_props
);
129 /* Technically this can't happen, but might as well have the
130 code ready in case that ever changes. */
131 return svn_error_createf(SVN_ERR_BAD_PROP_KIND
, NULL
,
132 "Bad property kind for property '%s'",
137 newprop
->name
= prop
->name
;
138 newprop
->value
= prop
->value
;
147 svn_prop_diffs(apr_array_header_t
**propdiffs
,
148 apr_hash_t
*target_props
,
149 apr_hash_t
*source_props
,
152 apr_hash_index_t
*hi
;
153 apr_array_header_t
*ary
= apr_array_make(pool
, 1, sizeof(svn_prop_t
));
155 /* Note: we will be storing the pointers to the keys (from the hashes)
156 into the propdiffs array. It is acceptable for us to
157 reference the same memory as the base/target_props hash. */
159 /* Loop over SOURCE_PROPS and examine each key. This will allow us to
160 detect any `deletion' events or `set-modification' events. */
161 for (hi
= apr_hash_first(pool
, source_props
); hi
; hi
= apr_hash_next(hi
))
166 const svn_string_t
*propval1
, *propval2
;
168 /* Get next property */
169 apr_hash_this(hi
, &key
, &klen
, &val
);
172 /* Does property name exist in TARGET_PROPS? */
173 propval2
= apr_hash_get(target_props
, key
, klen
);
175 if (propval2
== NULL
)
177 /* Add a delete event to the array */
178 svn_prop_t
*p
= apr_array_push(ary
);
182 else if (! svn_string_compare(propval1
, propval2
))
184 /* Add a set (modification) event to the array */
185 svn_prop_t
*p
= apr_array_push(ary
);
187 p
->value
= svn_string_dup(propval2
, pool
);
191 /* Loop over TARGET_PROPS and examine each key. This allows us to
192 detect `set-creation' events */
193 for (hi
= apr_hash_first(pool
, target_props
); hi
; hi
= apr_hash_next(hi
))
198 const svn_string_t
*propval
;
200 /* Get next property */
201 apr_hash_this(hi
, &key
, &klen
, &val
);
204 /* Does property name exist in SOURCE_PROPS? */
205 if (NULL
== apr_hash_get(source_props
, key
, klen
))
207 /* Add a set (creation) event to the array */
208 svn_prop_t
*p
= apr_array_push(ary
);
210 p
->value
= svn_string_dup(propval
, pool
);
214 /* Done building our array of user events. */
222 svn_prop_is_boolean(const char *prop_name
)
224 /* If we end up with more than 3 of these, we should probably put
225 them in a table and use bsearch. With only three, it doesn't
226 make any speed difference. */
227 if (strcmp(prop_name
, SVN_PROP_EXECUTABLE
) == 0
228 || strcmp(prop_name
, SVN_PROP_NEEDS_LOCK
) == 0
229 || strcmp(prop_name
, SVN_PROP_SPECIAL
) == 0)
236 svn_prop_needs_translation(const char *propname
)
238 /* ### Someday, we may want to be picky and choosy about which
239 properties require UTF8 and EOL conversion. For now, all "svn:"
242 return svn_prop_is_svn_prop(propname
);
247 svn_prop_name_is_valid(const char *prop_name
)
249 const char *p
= prop_name
;
251 /* The characters we allow use identical representations in UTF8
252 and ASCII, so we can just test for the appropriate ASCII codes.
253 But we can't use standard C character notation ('A', 'B', etc)
254 because there's no guarantee that this C environment is using
257 if (!(svn_ctype_isalpha(*p
)
258 || *p
== SVN_CTYPE_ASCII_COLON
259 || *p
== SVN_CTYPE_ASCII_UNDERSCORE
))
264 if (!(svn_ctype_isalnum(*p
)
265 || *p
== SVN_CTYPE_ASCII_MINUS
266 || *p
== SVN_CTYPE_ASCII_DOT
267 || *p
== SVN_CTYPE_ASCII_COLON
268 || *p
== SVN_CTYPE_ASCII_UNDERSCORE
))