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