source: valtobtest/subversion-1.6.2/subversion/libsvn_subr/properties.c @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

File size: 7.5 KB
Line 
1/*
2 * properties.c:  stuff related to Subversion properties
3 *
4 * ====================================================================
5 * Copyright (c) 2000-2006 CollabNet.  All rights reserved.
6 *
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.
12 *
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 * ====================================================================
17 */
18
19
20
21#include <apr_pools.h>
22#include <apr_hash.h>
23#include <apr_tables.h>
24#include <string.h>       /* for strncmp() */
25#include "svn_string.h"
26#include "svn_props.h"
27#include "svn_error.h"
28#include "svn_ctype.h"
29
30
31svn_boolean_t
32svn_prop_is_svn_prop(const char *prop_name)
33{
34  return strncmp(prop_name, SVN_PROP_PREFIX, (sizeof(SVN_PROP_PREFIX) - 1))
35         == 0;
36}
37
38
39svn_boolean_t
40svn_prop_has_svn_prop(const apr_hash_t *props, apr_pool_t *pool)
41{
42  apr_hash_index_t *hi;
43  const void *prop_name;
44
45  if (! props)
46    return FALSE;
47
48  for (hi = apr_hash_first(pool, (apr_hash_t *)props); hi;
49       hi = apr_hash_next(hi))
50    {
51      apr_hash_this(hi, &prop_name, NULL, NULL);
52      if (svn_prop_is_svn_prop((const char *) prop_name))
53        return TRUE;
54    }
55
56  return FALSE;
57}
58
59
60svn_prop_kind_t
61svn_property_kind(int *prefix_len,
62                  const char *prop_name)
63{
64  apr_size_t wc_prefix_len = sizeof(SVN_PROP_WC_PREFIX) - 1;
65  apr_size_t entry_prefix_len = sizeof(SVN_PROP_ENTRY_PREFIX) - 1;
66
67  if (strncmp(prop_name, SVN_PROP_WC_PREFIX, wc_prefix_len) == 0)
68    {
69      if (prefix_len)
70        *prefix_len = wc_prefix_len;
71      return svn_prop_wc_kind;
72    }
73
74  if (strncmp(prop_name, SVN_PROP_ENTRY_PREFIX, entry_prefix_len) == 0)
75    {
76      if (prefix_len)
77        *prefix_len = entry_prefix_len;
78      return svn_prop_entry_kind;
79    }
80
81  /* else... */
82  if (prefix_len)
83    *prefix_len = 0;
84  return svn_prop_regular_kind;
85}
86
87
88svn_error_t *
89svn_categorize_props(const apr_array_header_t *proplist,
90                     apr_array_header_t **entry_props,
91                     apr_array_header_t **wc_props,
92                     apr_array_header_t **regular_props,
93                     apr_pool_t *pool)
94{
95  int i;
96  if (entry_props)
97    *entry_props = apr_array_make(pool, 1, sizeof(svn_prop_t));
98  if (wc_props)
99    *wc_props = apr_array_make(pool, 1, sizeof(svn_prop_t));
100  if (regular_props)
101    *regular_props = apr_array_make(pool, 1, sizeof(svn_prop_t));
102
103  for (i = 0; i < proplist->nelts; i++)
104    {
105      svn_prop_t *prop, *newprop;
106      enum svn_prop_kind kind;
107
108      prop = &APR_ARRAY_IDX(proplist, i, svn_prop_t);
109      kind = svn_property_kind(NULL, prop->name);
110      newprop = NULL;
111
112      if (kind == svn_prop_regular_kind)
113        {
114          if (regular_props)
115            newprop = apr_array_push(*regular_props);
116        }
117      else if (kind == svn_prop_wc_kind)
118        {
119          if (wc_props)
120            newprop = apr_array_push(*wc_props);
121        }
122      else if (kind == svn_prop_entry_kind)
123        {
124          if (entry_props)
125            newprop = apr_array_push(*entry_props);
126        }
127      else
128        /* Technically this can't happen, but might as well have the
129           code ready in case that ever changes. */
130        return svn_error_createf(SVN_ERR_BAD_PROP_KIND, NULL,
131                                 "Bad property kind for property '%s'",
132                                 prop->name);
133
134      if (newprop)
135        {
136          newprop->name = prop->name;
137          newprop->value = prop->value;
138        }
139    }
140
141  return SVN_NO_ERROR;
142}
143
144
145svn_error_t *
146svn_prop_diffs(apr_array_header_t **propdiffs,
147               apr_hash_t *target_props,
148               apr_hash_t *source_props,
149               apr_pool_t *pool)
150{
151  apr_hash_index_t *hi;
152  apr_array_header_t *ary = apr_array_make(pool, 1, sizeof(svn_prop_t));
153
154  /* Note: we will be storing the pointers to the keys (from the hashes)
155     into the propdiffs array.  It is acceptable for us to
156     reference the same memory as the base/target_props hash. */
157
158  /* Loop over SOURCE_PROPS and examine each key.  This will allow us to
159     detect any `deletion' events or `set-modification' events.  */
160  for (hi = apr_hash_first(pool, source_props); hi; hi = apr_hash_next(hi))
161    {
162      const void *key;
163      apr_ssize_t klen;
164      void *val;
165      const svn_string_t *propval1, *propval2;
166
167      /* Get next property */
168      apr_hash_this(hi, &key, &klen, &val);
169      propval1 = val;
170
171      /* Does property name exist in TARGET_PROPS? */
172      propval2 = apr_hash_get(target_props, key, klen);
173
174      if (propval2 == NULL)
175        {
176          /* Add a delete event to the array */
177          svn_prop_t *p = apr_array_push(ary);
178          p->name = key;
179          p->value = NULL;
180        }
181      else if (! svn_string_compare(propval1, propval2))
182        {
183          /* Add a set (modification) event to the array */
184          svn_prop_t *p = apr_array_push(ary);
185          p->name = key;
186          p->value = svn_string_dup(propval2, pool);
187        }
188    }
189
190  /* Loop over TARGET_PROPS and examine each key.  This allows us to
191     detect `set-creation' events */
192  for (hi = apr_hash_first(pool, target_props); hi; hi = apr_hash_next(hi))
193    {
194      const void *key;
195      apr_ssize_t klen;
196      void *val;
197      const svn_string_t *propval;
198
199      /* Get next property */
200      apr_hash_this(hi, &key, &klen, &val);
201      propval = val;
202
203      /* Does property name exist in SOURCE_PROPS? */
204      if (NULL == apr_hash_get(source_props, key, klen))
205        {
206          /* Add a set (creation) event to the array */
207          svn_prop_t *p = apr_array_push(ary);
208          p->name = key;
209          p->value = svn_string_dup(propval, pool);
210        }
211    }
212
213  /* Done building our array of user events. */
214  *propdiffs = ary;
215
216  return SVN_NO_ERROR;
217}
218
219
220svn_boolean_t
221svn_prop_is_boolean(const char *prop_name)
222{
223  /* If we end up with more than 3 of these, we should probably put
224     them in a table and use bsearch.  With only three, it doesn't
225     make any speed difference.  */
226  if (strcmp(prop_name, SVN_PROP_EXECUTABLE) == 0
227      || strcmp(prop_name, SVN_PROP_NEEDS_LOCK) == 0
228      || strcmp(prop_name, SVN_PROP_SPECIAL) == 0)
229    return TRUE;
230  return FALSE;
231}
232
233
234svn_boolean_t
235svn_prop_needs_translation(const char *propname)
236{
237  /* ### Someday, we may want to be picky and choosy about which
238     properties require UTF8 and EOL conversion.  For now, all "svn:"
239     props need it.  */
240
241  return svn_prop_is_svn_prop(propname);
242}
243
244
245svn_boolean_t
246svn_prop_name_is_valid(const char *prop_name)
247{
248  const char *p = prop_name;
249
250  /* The characters we allow use identical representations in UTF8
251     and ASCII, so we can just test for the appropriate ASCII codes.
252     But we can't use standard C character notation ('A', 'B', etc)
253     because there's no guarantee that this C environment is using
254     ASCII. */
255
256  if (!(svn_ctype_isalpha(*p)
257        || *p == SVN_CTYPE_ASCII_COLON
258        || *p == SVN_CTYPE_ASCII_UNDERSCORE))
259    return FALSE;
260  p++;
261  for (; *p; p++)
262    {
263      if (!(svn_ctype_isalnum(*p)
264            || *p == SVN_CTYPE_ASCII_MINUS
265            || *p == SVN_CTYPE_ASCII_DOT
266            || *p == SVN_CTYPE_ASCII_COLON
267            || *p == SVN_CTYPE_ASCII_UNDERSCORE))
268        return FALSE;
269    }
270  return TRUE;
271}
Note: See TracBrowser for help on using the repository browser.