Change the format of the revprops block sent in svnserve for
[svn.git] / subversion / libsvn_fs_fs / id.c
blob515e1b0ec09c89f5aa0c7d75c4e92105eacb1385
1 /* id.c : operations on node-revision IDs
3 * ====================================================================
4 * Copyright (c) 2000-2004 CollabNet. All rights reserved.
6 * This software is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at http://subversion.tigris.org/license-1.html.
9 * If newer versions of this license are posted there, you may use a
10 * newer version instead, at your option.
12 * This software consists of voluntary contributions made by many
13 * individuals. For exact contribution history, see the revision
14 * history and logs, available at http://subversion.tigris.org/.
15 * ====================================================================
18 #include <string.h>
19 #include <stdlib.h>
21 #include "id.h"
22 #include "../libsvn_fs/fs-loader.h"
26 typedef struct {
27 const char *node_id;
28 const char *copy_id;
29 const char *txn_id;
30 svn_revnum_t rev;
31 apr_off_t offset;
32 } id_private_t;
35 /* Accessing ID Pieces. */
37 const char *
38 svn_fs_fs__id_node_id(const svn_fs_id_t *id)
40 id_private_t *pvt = id->fsap_data;
42 return pvt->node_id;
46 const char *
47 svn_fs_fs__id_copy_id(const svn_fs_id_t *id)
49 id_private_t *pvt = id->fsap_data;
51 return pvt->copy_id;
55 const char *
56 svn_fs_fs__id_txn_id(const svn_fs_id_t *id)
58 id_private_t *pvt = id->fsap_data;
60 return pvt->txn_id;
64 svn_revnum_t
65 svn_fs_fs__id_rev(const svn_fs_id_t *id)
67 id_private_t *pvt = id->fsap_data;
69 return pvt->rev;
73 apr_off_t
74 svn_fs_fs__id_offset(const svn_fs_id_t *id)
76 id_private_t *pvt = id->fsap_data;
78 return pvt->offset;
82 svn_string_t *
83 svn_fs_fs__id_unparse(const svn_fs_id_t *id,
84 apr_pool_t *pool)
86 const char *txn_rev_id;
87 id_private_t *pvt = id->fsap_data;
89 if ((! pvt->txn_id))
91 txn_rev_id = apr_psprintf(pool, "%ld/%"
92 APR_OFF_T_FMT, pvt->rev, pvt->offset);
94 else
96 txn_rev_id = pvt->txn_id;
98 return svn_string_createf(pool, "%s.%s.%c%s",
99 pvt->node_id, pvt->copy_id,
100 (pvt->txn_id ? 't' : 'r'),
101 txn_rev_id);
105 /*** Comparing node IDs ***/
107 svn_boolean_t
108 svn_fs_fs__id_eq(const svn_fs_id_t *a,
109 const svn_fs_id_t *b)
111 id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data;
113 if (a == b)
114 return TRUE;
115 if (strcmp(pvta->node_id, pvtb->node_id) != 0)
116 return FALSE;
117 if (strcmp(pvta->copy_id, pvtb->copy_id) != 0)
118 return FALSE;
119 if ((pvta->txn_id == NULL) != (pvtb->txn_id == NULL))
120 return FALSE;
121 if (pvta->txn_id && pvtb->txn_id && strcmp(pvta->txn_id, pvtb->txn_id) != 0)
122 return FALSE;
123 if (pvta->rev != pvtb->rev)
124 return FALSE;
125 if (pvta->offset != pvtb->offset)
126 return FALSE;
127 return TRUE;
131 svn_boolean_t
132 svn_fs_fs__id_check_related(const svn_fs_id_t *a,
133 const svn_fs_id_t *b)
135 id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data;
137 if (a == b)
138 return TRUE;
139 /* If both node_ids start with _ and they have differing transaction
140 IDs, then it is impossible for them to be related. */
141 if (pvta->node_id[0] == '_')
143 if (pvta->txn_id && pvtb->txn_id &&
144 (strcmp(pvta->txn_id, pvtb->txn_id) != 0))
145 return FALSE;
148 return (strcmp(pvta->node_id, pvtb->node_id) == 0) ? TRUE : FALSE;
153 svn_fs_fs__id_compare(const svn_fs_id_t *a,
154 const svn_fs_id_t *b)
156 if (svn_fs_fs__id_eq(a, b))
157 return 0;
158 return (svn_fs_fs__id_check_related(a, b) ? 1 : -1);
163 /* Creating ID's. */
165 static id_vtable_t id_vtable = {
166 svn_fs_fs__id_unparse,
167 svn_fs_fs__id_compare
171 svn_fs_id_t *
172 svn_fs_fs__id_txn_create(const char *node_id,
173 const char *copy_id,
174 const char *txn_id,
175 apr_pool_t *pool)
177 svn_fs_id_t *id = apr_palloc(pool, sizeof(*id));
178 id_private_t *pvt = apr_palloc(pool, sizeof(*pvt));
180 pvt->node_id = apr_pstrdup(pool, node_id);
181 pvt->copy_id = apr_pstrdup(pool, copy_id);
182 pvt->txn_id = apr_pstrdup(pool, txn_id);
183 pvt->rev = SVN_INVALID_REVNUM;
184 pvt->offset = -1;
185 id->vtable = &id_vtable;
186 id->fsap_data = pvt;
187 return id;
191 svn_fs_id_t *
192 svn_fs_fs__id_rev_create(const char *node_id,
193 const char *copy_id,
194 svn_revnum_t rev,
195 apr_off_t offset,
196 apr_pool_t *pool)
198 svn_fs_id_t *id = apr_palloc(pool, sizeof(*id));
199 id_private_t *pvt = apr_palloc(pool, sizeof(*pvt));
201 pvt->node_id = apr_pstrdup(pool, node_id);
202 pvt->copy_id = apr_pstrdup(pool, copy_id);
203 pvt->txn_id = NULL;
204 pvt->rev = rev;
205 pvt->offset = offset;
206 id->vtable = &id_vtable;
207 id->fsap_data = pvt;
208 return id;
212 svn_fs_id_t *
213 svn_fs_fs__id_copy(const svn_fs_id_t *id, apr_pool_t *pool)
215 svn_fs_id_t *new_id = apr_palloc(pool, sizeof(*new_id));
216 id_private_t *new_pvt = apr_palloc(pool, sizeof(*new_pvt));
217 id_private_t *pvt = id->fsap_data;
219 new_pvt->node_id = apr_pstrdup(pool, pvt->node_id);
220 new_pvt->copy_id = apr_pstrdup(pool, pvt->copy_id);
221 new_pvt->txn_id = pvt->txn_id ? apr_pstrdup(pool, pvt->txn_id) : NULL;
222 new_pvt->rev = pvt->rev;
223 new_pvt->offset = pvt->offset;
224 new_id->vtable = &id_vtable;
225 new_id->fsap_data = new_pvt;
226 return new_id;
230 svn_fs_id_t *
231 svn_fs_fs__id_parse(const char *data,
232 apr_size_t len,
233 apr_pool_t *pool)
235 svn_fs_id_t *id;
236 id_private_t *pvt;
237 char *data_copy, *str, *last_str;
239 /* Dup the ID data into POOL. Our returned ID will have references
240 into this memory. */
241 data_copy = apr_pstrmemdup(pool, data, len);
243 /* Alloc a new svn_fs_id_t structure. */
244 id = apr_palloc(pool, sizeof(*id));
245 pvt = apr_palloc(pool, sizeof(*pvt));
246 id->vtable = &id_vtable;
247 id->fsap_data = pvt;
249 /* Now, we basically just need to "split" this data on `.'
250 characters. We will use apr_strtok, which will put terminators
251 where each of the '.'s used to be. Then our new id field will
252 reference string locations inside our duplicate string.*/
254 /* Node Id */
255 str = apr_strtok(data_copy, ".", &last_str);
256 if (str == NULL)
257 return NULL;
258 pvt->node_id = str;
260 /* Copy Id */
261 str = apr_strtok(NULL, ".", &last_str);
262 if (str == NULL)
263 return NULL;
264 pvt->copy_id = str;
266 /* Txn/Rev Id */
267 str = apr_strtok(NULL, ".", &last_str);
268 if (str == NULL)
269 return NULL;
271 if (str[0] == 'r')
273 /* This is a revision type ID */
274 pvt->txn_id = NULL;
276 str = apr_strtok(str + 1, "/", &last_str);
277 if (str == NULL)
278 return NULL;
279 pvt->rev = SVN_STR_TO_REV(str);
281 str = apr_strtok(NULL, "/", &last_str);
282 if (str == NULL)
283 return NULL;
284 pvt->offset = apr_atoi64(str);
286 else if (str[0] == 't')
288 /* This is a transaction type ID */
289 pvt->txn_id = str + 1;
290 pvt->rev = SVN_INVALID_REVNUM;
291 pvt->offset = -1;
293 else
294 return NULL;
296 return id;