xref: /trueos/contrib/subversion/subversion/libsvn_subr/types.c (revision 1e5107043085964bba002e6a91aa04e864f74d02)
1 /*
2  * svn_types.c :  Implementation for Subversion's data types.
3  *
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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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  * ====================================================================
22  */
23 
24 #include <apr_pools.h>
25 #include <apr_uuid.h>
26 
27 #include "svn_hash.h"
28 #include "svn_types.h"
29 #include "svn_error.h"
30 #include "svn_string.h"
31 #include "svn_props.h"
32 #include "svn_private_config.h"
33 
34 svn_error_t *
svn_revnum_parse(svn_revnum_t * rev,const char * str,const char ** endptr)35 svn_revnum_parse(svn_revnum_t *rev,
36                  const char *str,
37                  const char **endptr)
38 {
39   char *end;
40 
41   svn_revnum_t result = strtol(str, &end, 10);
42 
43   if (endptr)
44     *endptr = end;
45 
46   if (str == end)
47     return svn_error_createf(SVN_ERR_REVNUM_PARSE_FAILURE, NULL,
48                              _("Invalid revision number found parsing '%s'"),
49                              str);
50 
51   if (result < 0)
52     {
53       /* The end pointer from strtol() is valid, but a negative revision
54          number is invalid, so move the end pointer back to the
55          beginning of the string. */
56       if (endptr)
57         *endptr = str;
58 
59       return svn_error_createf(SVN_ERR_REVNUM_PARSE_FAILURE, NULL,
60                                _("Negative revision number found parsing '%s'"),
61                                str);
62     }
63 
64   *rev = result;
65 
66   return SVN_NO_ERROR;
67 }
68 
69 const char *
svn_uuid_generate(apr_pool_t * pool)70 svn_uuid_generate(apr_pool_t *pool)
71 {
72   apr_uuid_t uuid;
73   char *uuid_str = apr_pcalloc(pool, APR_UUID_FORMATTED_LENGTH + 1);
74   apr_uuid_get(&uuid);
75   apr_uuid_format(uuid_str, &uuid);
76   return uuid_str;
77 }
78 
79 const char *
svn_depth_to_word(svn_depth_t depth)80 svn_depth_to_word(svn_depth_t depth)
81 {
82   switch (depth)
83     {
84     case svn_depth_exclude:
85       return "exclude";
86     case svn_depth_unknown:
87       return "unknown";
88     case svn_depth_empty:
89       return "empty";
90     case svn_depth_files:
91       return "files";
92     case svn_depth_immediates:
93       return "immediates";
94     case svn_depth_infinity:
95       return "infinity";
96     default:
97       return "INVALID-DEPTH";
98     }
99 }
100 
101 
102 svn_depth_t
svn_depth_from_word(const char * word)103 svn_depth_from_word(const char *word)
104 {
105   if (strcmp(word, "exclude") == 0)
106     return svn_depth_exclude;
107   if (strcmp(word, "unknown") == 0)
108     return svn_depth_unknown;
109   if (strcmp(word, "empty") == 0)
110     return svn_depth_empty;
111   if (strcmp(word, "files") == 0)
112     return svn_depth_files;
113   if (strcmp(word, "immediates") == 0)
114     return svn_depth_immediates;
115   if (strcmp(word, "infinity") == 0)
116     return svn_depth_infinity;
117   /* There's no special value for invalid depth, and no convincing
118      reason to make one yet, so just fall back to unknown depth.
119      If you ever change that convention, check callers to make sure
120      they're not depending on it (e.g., option parsing in main() ).
121   */
122   return svn_depth_unknown;
123 }
124 
125 const char *
svn_node_kind_to_word(svn_node_kind_t kind)126 svn_node_kind_to_word(svn_node_kind_t kind)
127 {
128   switch (kind)
129     {
130     case svn_node_none:
131       return "none";
132     case svn_node_file:
133       return "file";
134     case svn_node_dir:
135       return "dir";
136     case svn_node_symlink:
137       return "symlink";
138     case svn_node_unknown:
139     default:
140       return "unknown";
141     }
142 }
143 
144 
145 svn_node_kind_t
svn_node_kind_from_word(const char * word)146 svn_node_kind_from_word(const char *word)
147 {
148   if (word == NULL)
149     return svn_node_unknown;
150 
151   if (strcmp(word, "none") == 0)
152     return svn_node_none;
153   else if (strcmp(word, "file") == 0)
154     return svn_node_file;
155   else if (strcmp(word, "dir") == 0)
156     return svn_node_dir;
157   else if (strcmp(word, "symlink") == 0)
158     return svn_node_symlink;
159   else
160     /* This also handles word == "unknown" */
161     return svn_node_unknown;
162 }
163 
164 const char *
svn_tristate__to_word(svn_tristate_t tristate)165 svn_tristate__to_word(svn_tristate_t tristate)
166 {
167   switch (tristate)
168     {
169       case svn_tristate_false:
170         return "false";
171       case svn_tristate_true:
172         return "true";
173       case svn_tristate_unknown:
174       default:
175         return NULL;
176     }
177 }
178 
179 svn_tristate_t
svn_tristate__from_word(const char * word)180 svn_tristate__from_word(const char *word)
181 {
182   if (word == NULL)
183     return svn_tristate_unknown;
184   else if (0 == svn_cstring_casecmp(word, "true")
185            || 0 == svn_cstring_casecmp(word, "yes")
186            || 0 == svn_cstring_casecmp(word, "on")
187            || 0 == strcmp(word, "1"))
188     return svn_tristate_true;
189   else if (0 == svn_cstring_casecmp(word, "false")
190            || 0 == svn_cstring_casecmp(word, "no")
191            || 0 == svn_cstring_casecmp(word, "off")
192            || 0 == strcmp(word, "0"))
193     return svn_tristate_false;
194 
195   return svn_tristate_unknown;
196 }
197 
198 svn_commit_info_t *
svn_create_commit_info(apr_pool_t * pool)199 svn_create_commit_info(apr_pool_t *pool)
200 {
201   svn_commit_info_t *commit_info
202     = apr_pcalloc(pool, sizeof(*commit_info));
203 
204   commit_info->revision = SVN_INVALID_REVNUM;
205   /* All other fields were initialized to NULL above. */
206 
207   return commit_info;
208 }
209 
210 svn_commit_info_t *
svn_commit_info_dup(const svn_commit_info_t * src_commit_info,apr_pool_t * pool)211 svn_commit_info_dup(const svn_commit_info_t *src_commit_info,
212                     apr_pool_t *pool)
213 {
214   svn_commit_info_t *dst_commit_info
215     = apr_palloc(pool, sizeof(*dst_commit_info));
216 
217   dst_commit_info->date = src_commit_info->date
218     ? apr_pstrdup(pool, src_commit_info->date) : NULL;
219   dst_commit_info->author = src_commit_info->author
220     ? apr_pstrdup(pool, src_commit_info->author) : NULL;
221   dst_commit_info->revision = src_commit_info->revision;
222   dst_commit_info->post_commit_err = src_commit_info->post_commit_err
223     ? apr_pstrdup(pool, src_commit_info->post_commit_err) : NULL;
224   dst_commit_info->repos_root = src_commit_info->repos_root
225     ? apr_pstrdup(pool, src_commit_info->repos_root) : NULL;
226 
227   return dst_commit_info;
228 }
229 
230 svn_log_changed_path2_t *
svn_log_changed_path2_create(apr_pool_t * pool)231 svn_log_changed_path2_create(apr_pool_t *pool)
232 {
233   svn_log_changed_path2_t *new_changed_path
234     = apr_pcalloc(pool, sizeof(*new_changed_path));
235 
236   new_changed_path->text_modified = svn_tristate_unknown;
237   new_changed_path->props_modified = svn_tristate_unknown;
238 
239   return new_changed_path;
240 }
241 
242 svn_log_changed_path2_t *
svn_log_changed_path2_dup(const svn_log_changed_path2_t * changed_path,apr_pool_t * pool)243 svn_log_changed_path2_dup(const svn_log_changed_path2_t *changed_path,
244                           apr_pool_t *pool)
245 {
246   svn_log_changed_path2_t *new_changed_path
247     = apr_palloc(pool, sizeof(*new_changed_path));
248 
249   *new_changed_path = *changed_path;
250 
251   if (new_changed_path->copyfrom_path)
252     new_changed_path->copyfrom_path =
253       apr_pstrdup(pool, new_changed_path->copyfrom_path);
254 
255   return new_changed_path;
256 }
257 
258 svn_dirent_t *
svn_dirent_create(apr_pool_t * result_pool)259 svn_dirent_create(apr_pool_t *result_pool)
260 {
261   svn_dirent_t *new_dirent = apr_pcalloc(result_pool, sizeof(*new_dirent));
262 
263   new_dirent->kind = svn_node_unknown;
264   new_dirent->size = SVN_INVALID_FILESIZE;
265   new_dirent->created_rev = SVN_INVALID_REVNUM;
266   new_dirent->time = 0;
267   new_dirent->last_author = NULL;
268 
269   return new_dirent;
270 }
271 
272 svn_dirent_t *
svn_dirent_dup(const svn_dirent_t * dirent,apr_pool_t * pool)273 svn_dirent_dup(const svn_dirent_t *dirent,
274                apr_pool_t *pool)
275 {
276   svn_dirent_t *new_dirent = apr_palloc(pool, sizeof(*new_dirent));
277 
278   *new_dirent = *dirent;
279 
280   new_dirent->last_author = apr_pstrdup(pool, dirent->last_author);
281 
282   return new_dirent;
283 }
284 
285 svn_log_entry_t *
svn_log_entry_create(apr_pool_t * pool)286 svn_log_entry_create(apr_pool_t *pool)
287 {
288   svn_log_entry_t *log_entry = apr_pcalloc(pool, sizeof(*log_entry));
289 
290   return log_entry;
291 }
292 
293 svn_log_entry_t *
svn_log_entry_dup(const svn_log_entry_t * log_entry,apr_pool_t * pool)294 svn_log_entry_dup(const svn_log_entry_t *log_entry, apr_pool_t *pool)
295 {
296   apr_hash_index_t *hi;
297   svn_log_entry_t *new_entry = apr_palloc(pool, sizeof(*new_entry));
298 
299   *new_entry = *log_entry;
300 
301   if (log_entry->revprops)
302     new_entry->revprops = svn_prop_hash_dup(log_entry->revprops, pool);
303 
304   if (log_entry->changed_paths2)
305     {
306       new_entry->changed_paths2 = apr_hash_make(pool);
307 
308       for (hi = apr_hash_first(pool, log_entry->changed_paths2);
309            hi; hi = apr_hash_next(hi))
310         {
311           const void *key;
312           void *change;
313 
314           apr_hash_this(hi, &key, NULL, &change);
315 
316           svn_hash_sets(new_entry->changed_paths2, apr_pstrdup(pool, key),
317                         svn_log_changed_path2_dup(change, pool));
318         }
319     }
320 
321   /* We can't copy changed_paths by itself without using deprecated code,
322      but we don't have to, as this function was new after the introduction
323      of the changed_paths2 field. */
324   new_entry->changed_paths = new_entry->changed_paths2;
325 
326   return new_entry;
327 }
328 
329 svn_location_segment_t *
svn_location_segment_dup(const svn_location_segment_t * segment,apr_pool_t * pool)330 svn_location_segment_dup(const svn_location_segment_t *segment,
331                          apr_pool_t *pool)
332 {
333   svn_location_segment_t *new_segment =
334     apr_palloc(pool, sizeof(*new_segment));
335 
336   *new_segment = *segment;
337   if (segment->path)
338     new_segment->path = apr_pstrdup(pool, segment->path);
339   return new_segment;
340 }
341