diff options
Diffstat (limited to 'subversion/libsvn_fs_fs/temp_serializer.c')
-rw-r--r-- | subversion/libsvn_fs_fs/temp_serializer.c | 535 |
1 files changed, 462 insertions, 73 deletions
diff --git a/subversion/libsvn_fs_fs/temp_serializer.c b/subversion/libsvn_fs_fs/temp_serializer.c index cb0bb6b..0178143 100644 --- a/subversion/libsvn_fs_fs/temp_serializer.c +++ b/subversion/libsvn_fs_fs/temp_serializer.c @@ -30,6 +30,7 @@ #include "private/svn_fs_util.h" #include "private/svn_temp_serializer.h" +#include "private/svn_subr_private.h" #include "temp_serializer.h" @@ -47,16 +48,16 @@ encode_number(apr_int64_t number, char *key_buffer) if (number < 0) { number = -number; - *key_buffer = (number & 63) + ' ' + 65; + *key_buffer = (char)((number & 63) + ' ' + 65); } else - *key_buffer = (number & 63) + ' ' + 1; + *key_buffer = (char)((number & 63) + ' ' + 1); number /= 64; /* write 7 bits / byte until no significant bits are left */ while (number) { - *++key_buffer = (number & 127) + ' ' + 1; + *++key_buffer = (char)((number & 127) + ' ' + 1); number /= 128; } @@ -64,10 +65,6 @@ encode_number(apr_int64_t number, char *key_buffer) return key_buffer; } -/* Prepend the NUMBER to the STRING in a space efficient way that no other - * (number,string) combination can produce the same result. - * Allocate temporaries as well as the result from POOL. - */ const char* svn_fs_fs__combine_number_and_string(apr_int64_t number, const char *string, @@ -91,31 +88,6 @@ svn_fs_fs__combine_number_and_string(apr_int64_t number, return key; } -/* Combine the numbers A and B a space efficient way that no other - * combination of numbers can produce the same result. - * Allocate temporaries as well as the result from POOL. - */ -const char* -svn_fs_fs__combine_two_numbers(apr_int64_t a, - apr_int64_t b, - apr_pool_t *pool) -{ - /* encode numbers as 2x 10x7 bits + 1 space + 1 terminating \0*/ - char *key_buffer = apr_palloc(pool, 22); - const char *key = key_buffer; - - /* combine the numbers. Since the separator is disjoint from any part - * of the encoded numbers, there is no other combination that can yield - * the same result */ - key_buffer = encode_number(a, key_buffer); - *++key_buffer = ' '; - key_buffer = encode_number(b, ++key_buffer); - *++key_buffer = '\0'; - - /* return the start of the key */ - return key; -} - /* Utility function to serialize string S in the given serialization CONTEXT. */ static void @@ -136,7 +108,7 @@ serialize_svn_string(svn_temp_serializer__context_t *context, * Thus, we cannot use svn_temp_serializer__add_string. */ svn_temp_serializer__push(context, (const void * const *)&string->data, - string->len); + string->len + 1); /* back to the caller's nesting level */ svn_temp_serializer__pop(context); @@ -184,7 +156,7 @@ serialize_checksum(svn_temp_serializer__context_t *context, /* Utility function to deserialize the checksum CS inside the BUFFER. */ static void -deserialize_checksum(void *buffer, svn_checksum_t * const *cs) +deserialize_checksum(void *buffer, svn_checksum_t **cs) { svn_temp_deserializer__resolve(buffer, (void **)cs); if (*cs == NULL) @@ -367,7 +339,7 @@ serialize_dir(apr_hash_t *entries, apr_pool_t *pool) static apr_hash_t * deserialize_dir(void *buffer, hash_data_t *hash_data, apr_pool_t *pool) { - apr_hash_t *result = apr_hash_make(pool); + apr_hash_t *result = svn_hash__make(pool); apr_size_t i; apr_size_t count; svn_fs_dirent_t *entry; @@ -388,7 +360,7 @@ deserialize_dir(void *buffer, hash_data_t *hash_data, apr_pool_t *pool) svn_fs_fs__id_deserialize(entry, (svn_fs_id_t **)&entry->id); /* add the entry to the hash */ - apr_hash_set(result, entry->name, APR_HASH_KEY_STRING, entry); + svn_hash_sets(result, entry->name, entry); } /* return the now complete hash */ @@ -489,7 +461,7 @@ serialize_txdeltawindow(svn_temp_serializer__context_t *context, } svn_error_t * -svn_fs_fs__serialize_txdelta_window(char **buffer, +svn_fs_fs__serialize_txdelta_window(void **buffer, apr_size_t *buffer_size, void *item, apr_pool_t *pool) @@ -522,7 +494,7 @@ svn_fs_fs__serialize_txdelta_window(char **buffer, svn_error_t * svn_fs_fs__deserialize_txdelta_window(void **item, - char *buffer, + void *buffer, apr_size_t buffer_size, apr_pool_t *pool) { @@ -548,7 +520,7 @@ svn_fs_fs__deserialize_txdelta_window(void **item, } svn_error_t * -svn_fs_fs__serialize_manifest(char **data, +svn_fs_fs__serialize_manifest(void **data, apr_size_t *data_len, void *in, apr_pool_t *pool) @@ -564,7 +536,7 @@ svn_fs_fs__serialize_manifest(char **data, svn_error_t * svn_fs_fs__deserialize_manifest(void **out, - char *data, + void *data, apr_size_t data_len, apr_pool_t *pool) { @@ -579,8 +551,144 @@ svn_fs_fs__deserialize_manifest(void **out, return SVN_NO_ERROR; } +/* Auxilliary structure representing the content of a properties hash. + This structure is much easier to (de-)serialize than an apr_hash. + */ +typedef struct properties_data_t +{ + /* number of entries in the hash */ + apr_size_t count; + + /* reference to the keys */ + const char **keys; + + /* reference to the values */ + const svn_string_t **values; +} properties_data_t; + +/* Serialize COUNT C-style strings from *STRINGS into CONTEXT. */ +static void +serialize_cstring_array(svn_temp_serializer__context_t *context, + const char ***strings, + apr_size_t count) +{ + apr_size_t i; + const char **entries = *strings; + + /* serialize COUNT entries pointers (the array) */ + svn_temp_serializer__push(context, + (const void * const *)strings, + count * sizeof(const char*)); + + /* serialize array elements */ + for (i = 0; i < count; ++i) + svn_temp_serializer__add_string(context, &entries[i]); + + svn_temp_serializer__pop(context); +} + +/* Serialize COUNT svn_string_t* items from *STRINGS into CONTEXT. */ +static void +serialize_svn_string_array(svn_temp_serializer__context_t *context, + const svn_string_t ***strings, + apr_size_t count) +{ + apr_size_t i; + const svn_string_t **entries = *strings; + + /* serialize COUNT entries pointers (the array) */ + svn_temp_serializer__push(context, + (const void * const *)strings, + count * sizeof(const char*)); + + /* serialize array elements */ + for (i = 0; i < count; ++i) + serialize_svn_string(context, &entries[i]); + + svn_temp_serializer__pop(context); +} + +svn_error_t * +svn_fs_fs__serialize_properties(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool) +{ + apr_hash_t *hash = in; + properties_data_t properties; + svn_temp_serializer__context_t *context; + apr_hash_index_t *hi; + svn_stringbuf_t *serialized; + apr_size_t i; + + /* create our auxilliary data structure */ + properties.count = apr_hash_count(hash); + properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1)); + properties.values = apr_palloc(pool, sizeof(const char*) * properties.count); + + /* populate it with the hash entries */ + for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i) + { + properties.keys[i] = svn__apr_hash_index_key(hi); + properties.values[i] = svn__apr_hash_index_val(hi); + } + + /* serialize it */ + context = svn_temp_serializer__init(&properties, + sizeof(properties), + properties.count * 100, + pool); + + properties.keys[i] = ""; + serialize_cstring_array(context, &properties.keys, properties.count + 1); + serialize_svn_string_array(context, &properties.values, properties.count); + + /* return the serialized result */ + serialized = svn_temp_serializer__get(context); + + *data = serialized->data; + *data_len = serialized->len; + + return SVN_NO_ERROR; +} + svn_error_t * -svn_fs_fs__serialize_id(char **data, +svn_fs_fs__deserialize_properties(void **out, + void *data, + apr_size_t data_len, + apr_pool_t *pool) +{ + apr_hash_t *hash = svn_hash__make(pool); + properties_data_t *properties = (properties_data_t *)data; + size_t i; + + /* de-serialize our auxilliary data structure */ + svn_temp_deserializer__resolve(properties, (void**)&properties->keys); + svn_temp_deserializer__resolve(properties, (void**)&properties->values); + + /* de-serialize each entry and put it into the hash */ + for (i = 0; i < properties->count; ++i) + { + apr_size_t len = properties->keys[i+1] - properties->keys[i] - 1; + svn_temp_deserializer__resolve((void*)properties->keys, + (void**)&properties->keys[i]); + + deserialize_svn_string((void*)properties->values, + (svn_string_t **)&properties->values[i]); + + apr_hash_set(hash, + properties->keys[i], len, + properties->values[i]); + } + + /* done */ + *out = hash; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_fs__serialize_id(void **data, apr_size_t *data_len, void *in, apr_pool_t *pool) @@ -605,7 +713,7 @@ svn_fs_fs__serialize_id(char **data, svn_error_t * svn_fs_fs__deserialize_id(void **out, - char *data, + void *data, apr_size_t data_len, apr_pool_t *pool) { @@ -623,17 +731,20 @@ svn_fs_fs__deserialize_id(void **out, /** Caching node_revision_t objects. **/ svn_error_t * -svn_fs_fs__serialize_node_revision(char **buffer, - apr_size_t *buffer_size, - void *item, - apr_pool_t *pool) +svn_fs_fs__serialize_node_revision(void **buffer, + apr_size_t *buffer_size, + void *item, + apr_pool_t *pool) { svn_stringbuf_t *serialized; node_revision_t *noderev = item; - /* create an (empty) serialization context with plenty of buffer space */ + /* create an (empty) serialization context with plenty of (initial) + * buffer space. */ svn_temp_serializer__context_t *context = - svn_temp_serializer__init(NULL, 0, 503, pool); + svn_temp_serializer__init(NULL, 0, + 1024 - SVN_TEMP_SERIALIZER__OVERHEAD, + pool); /* serialize the noderev */ svn_fs_fs__noderev_serialize(context, &noderev); @@ -648,7 +759,7 @@ svn_fs_fs__serialize_node_revision(char **buffer, svn_error_t * svn_fs_fs__deserialize_node_revision(void **item, - char *buffer, + void *buffer, apr_size_t buffer_size, apr_pool_t *pool) { @@ -667,7 +778,7 @@ svn_fs_fs__deserialize_node_revision(void **item, * to DATA and DATA_LEN. */ static svn_error_t * return_serialized_dir_context(svn_temp_serializer__context_t *context, - char **data, + void **data, apr_size_t *data_len) { svn_stringbuf_t *serialized = svn_temp_serializer__get(context); @@ -680,7 +791,7 @@ return_serialized_dir_context(svn_temp_serializer__context_t *context, } svn_error_t * -svn_fs_fs__serialize_dir_entries(char **data, +svn_fs_fs__serialize_dir_entries(void **data, apr_size_t *data_len, void *in, apr_pool_t *pool) @@ -696,7 +807,7 @@ svn_fs_fs__serialize_dir_entries(char **data, svn_error_t * svn_fs_fs__deserialize_dir_entries(void **out, - char *data, + void *data, apr_size_t data_len, apr_pool_t *pool) { @@ -711,12 +822,12 @@ svn_fs_fs__deserialize_dir_entries(void **out, svn_error_t * svn_fs_fs__get_sharded_offset(void **out, - const char *data, + const void *data, apr_size_t data_len, void *baton, apr_pool_t *pool) { - apr_off_t *manifest = (apr_off_t *)data; + const apr_off_t *manifest = data; apr_int64_t shard_pos = *(apr_int64_t *)baton; *(apr_off_t *)out = manifest[shard_pos]; @@ -743,9 +854,9 @@ find_entry(svn_fs_dirent_t **entries, for (middle = upper / 2; lower < upper; middle = (upper + lower) / 2) { const svn_fs_dirent_t *entry = - svn_temp_deserializer__ptr(entries, (const void **)&entries[middle]); + svn_temp_deserializer__ptr(entries, (const void *const *)&entries[middle]); const char* entry_name = - svn_temp_deserializer__ptr(entry, (const void **)&entry->name); + svn_temp_deserializer__ptr(entry, (const void *const *)&entry->name); int diff = strcmp(entry_name, name); if (diff < 0) @@ -759,9 +870,9 @@ find_entry(svn_fs_dirent_t **entries, if (lower < count) { const svn_fs_dirent_t *entry = - svn_temp_deserializer__ptr(entries, (const void **)&entries[lower]); + svn_temp_deserializer__ptr(entries, (const void *const *)&entries[lower]); const char* entry_name = - svn_temp_deserializer__ptr(entry, (const void **)&entry->name); + svn_temp_deserializer__ptr(entry, (const void *const *)&entry->name); if (strcmp(entry_name, name) == 0) *found = TRUE; @@ -772,22 +883,22 @@ find_entry(svn_fs_dirent_t **entries, svn_error_t * svn_fs_fs__extract_dir_entry(void **out, - const char *data, + const void *data, apr_size_t data_len, void *baton, apr_pool_t *pool) { - hash_data_t *hash_data = (hash_data_t *)data; + const hash_data_t *hash_data = data; const char* name = baton; svn_boolean_t found; /* resolve the reference to the entries array */ const svn_fs_dirent_t * const *entries = - svn_temp_deserializer__ptr(data, (const void **)&hash_data->entries); + svn_temp_deserializer__ptr(data, (const void *const *)&hash_data->entries); /* resolve the reference to the lengths array */ const apr_uint32_t *lengths = - svn_temp_deserializer__ptr(data, (const void **)&hash_data->lengths); + svn_temp_deserializer__ptr(data, (const void *const *)&hash_data->lengths); /* binary search for the desired entry by name */ apr_size_t pos = find_entry((svn_fs_dirent_t **)entries, @@ -800,10 +911,10 @@ svn_fs_fs__extract_dir_entry(void **out, if (found) { const svn_fs_dirent_t *source = - svn_temp_deserializer__ptr(entries, (const void **)&entries[pos]); + svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]); /* Entries have been serialized one-by-one, each time including all - * nestes structures and strings. Therefore, they occupy a single + * nested structures and strings. Therefore, they occupy a single * block of memory whose end-offset is either the beginning of the * next entry or the end of the buffer */ @@ -825,7 +936,7 @@ svn_fs_fs__extract_dir_entry(void **out, * modification as a simply deserialize / modify / serialize sequence. */ static svn_error_t * -slowly_replace_dir_entry(char **data, +slowly_replace_dir_entry(void **data, apr_size_t *data_len, void *baton, apr_pool_t *pool) @@ -838,16 +949,13 @@ slowly_replace_dir_entry(char **data, *data, hash_data->len, pool)); - apr_hash_set(dir, - replace_baton->name, - APR_HASH_KEY_STRING, - replace_baton->new_entry); + svn_hash_sets(dir, replace_baton->name, replace_baton->new_entry); return svn_fs_fs__serialize_dir_entries(data, data_len, dir, pool); } svn_error_t * -svn_fs_fs__replace_dir_entry(char **data, +svn_fs_fs__replace_dir_entry(void **data, apr_size_t *data_len, void *baton, apr_pool_t *pool) @@ -871,12 +979,12 @@ svn_fs_fs__replace_dir_entry(char **data, /* resolve the reference to the entries array */ entries = (svn_fs_dirent_t **) svn_temp_deserializer__ptr((const char *)hash_data, - (const void **)&hash_data->entries); + (const void *const *)&hash_data->entries); /* resolve the reference to the lengths array */ lengths = (apr_uint32_t *) svn_temp_deserializer__ptr((const char *)hash_data, - (const void **)&hash_data->lengths); + (const void *const *)&hash_data->lengths); /* binary search for the desired entry by name */ pos = find_entry(entries, replace_baton->name, hash_data->count, &found); @@ -945,8 +1053,289 @@ svn_fs_fs__replace_dir_entry(char **data, hash_data = (hash_data_t *)*data; lengths = (apr_uint32_t *) svn_temp_deserializer__ptr((const char *)hash_data, - (const void **)&hash_data->lengths); + (const void *const *)&hash_data->lengths); lengths[pos] = length; return SVN_NO_ERROR; } + +/* Utility function to serialize change CHANGE_P in the given serialization + * CONTEXT. + */ +static void +serialize_change(svn_temp_serializer__context_t *context, + change_t * const *change_p) +{ + const change_t * change = *change_p; + if (change == NULL) + return; + + /* serialize the change struct itself */ + svn_temp_serializer__push(context, + (const void * const *)change_p, + sizeof(*change)); + + /* serialize sub-structures */ + svn_fs_fs__id_serialize(context, &change->noderev_id); + + svn_temp_serializer__add_string(context, &change->path); + svn_temp_serializer__add_string(context, &change->copyfrom_path); + + /* return to the caller's nesting level */ + svn_temp_serializer__pop(context); +} + +/* Utility function to serialize the CHANGE_P within the given + * serialization CONTEXT. + */ +static void +deserialize_change(void *buffer, change_t **change_p) +{ + change_t * change; + + /* fix-up of the pointer to the struct in question */ + svn_temp_deserializer__resolve(buffer, (void **)change_p); + + change = *change_p; + if (change == NULL) + return; + + /* fix-up of sub-structures */ + svn_fs_fs__id_deserialize(change, (svn_fs_id_t **)&change->noderev_id); + + svn_temp_deserializer__resolve(change, (void **)&change->path); + svn_temp_deserializer__resolve(change, (void **)&change->copyfrom_path); +} + +/* Auxiliary structure representing the content of a change_t array. + This structure is much easier to (de-)serialize than an APR array. + */ +typedef struct changes_data_t +{ + /* number of entries in the array */ + int count; + + /* reference to the changes */ + change_t **changes; +} changes_data_t; + +svn_error_t * +svn_fs_fs__serialize_changes(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool) +{ + apr_array_header_t *array = in; + changes_data_t changes; + svn_temp_serializer__context_t *context; + svn_stringbuf_t *serialized; + int i; + + /* initialize our auxiliary data structure */ + changes.count = array->nelts; + changes.changes = apr_palloc(pool, sizeof(change_t*) * changes.count); + + /* populate it with the array elements */ + for (i = 0; i < changes.count; ++i) + changes.changes[i] = APR_ARRAY_IDX(array, i, change_t*); + + /* serialize it and all its elements */ + context = svn_temp_serializer__init(&changes, + sizeof(changes), + changes.count * 100, + pool); + + svn_temp_serializer__push(context, + (const void * const *)&changes.changes, + changes.count * sizeof(change_t*)); + + for (i = 0; i < changes.count; ++i) + serialize_change(context, &changes.changes[i]); + + svn_temp_serializer__pop(context); + + /* return the serialized result */ + serialized = svn_temp_serializer__get(context); + + *data = serialized->data; + *data_len = serialized->len; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_fs__deserialize_changes(void **out, + void *data, + apr_size_t data_len, + apr_pool_t *pool) +{ + int i; + changes_data_t *changes = (changes_data_t *)data; + apr_array_header_t *array = apr_array_make(pool, changes->count, + sizeof(change_t *)); + + /* de-serialize our auxiliary data structure */ + svn_temp_deserializer__resolve(changes, (void**)&changes->changes); + + /* de-serialize each entry and add it to the array */ + for (i = 0; i < changes->count; ++i) + { + deserialize_change((void*)changes->changes, + (change_t **)&changes->changes[i]); + APR_ARRAY_PUSH(array, change_t *) = changes->changes[i]; + } + + /* done */ + *out = array; + + return SVN_NO_ERROR; +} + +/* Auxiliary structure representing the content of a svn_mergeinfo_t hash. + This structure is much easier to (de-)serialize than an APR array. + */ +typedef struct mergeinfo_data_t +{ + /* number of paths in the hash */ + unsigned count; + + /* COUNT keys (paths) */ + const char **keys; + + /* COUNT keys lengths (strlen of path) */ + apr_ssize_t *key_lengths; + + /* COUNT entries, each giving the number of ranges for the key */ + int *range_counts; + + /* all ranges in a single, concatenated buffer */ + svn_merge_range_t *ranges; +} mergeinfo_data_t; + +svn_error_t * +svn_fs_fs__serialize_mergeinfo(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool) +{ + svn_mergeinfo_t mergeinfo = in; + mergeinfo_data_t merges; + svn_temp_serializer__context_t *context; + svn_stringbuf_t *serialized; + apr_hash_index_t *hi; + unsigned i; + int k; + apr_size_t range_count; + + /* initialize our auxiliary data structure */ + merges.count = apr_hash_count(mergeinfo); + merges.keys = apr_palloc(pool, sizeof(*merges.keys) * merges.count); + merges.key_lengths = apr_palloc(pool, sizeof(*merges.key_lengths) * + merges.count); + merges.range_counts = apr_palloc(pool, sizeof(*merges.range_counts) * + merges.count); + + i = 0; + range_count = 0; + for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi), ++i) + { + svn_rangelist_t *ranges; + apr_hash_this(hi, (const void**)&merges.keys[i], + &merges.key_lengths[i], + (void **)&ranges); + merges.range_counts[i] = ranges->nelts; + range_count += ranges->nelts; + } + + merges.ranges = apr_palloc(pool, sizeof(*merges.ranges) * range_count); + + i = 0; + for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi)) + { + svn_rangelist_t *ranges = svn__apr_hash_index_val(hi); + for (k = 0; k < ranges->nelts; ++k, ++i) + merges.ranges[i] = *APR_ARRAY_IDX(ranges, k, svn_merge_range_t*); + } + + /* serialize it and all its elements */ + context = svn_temp_serializer__init(&merges, + sizeof(merges), + range_count * 30, + pool); + + /* keys array */ + svn_temp_serializer__push(context, + (const void * const *)&merges.keys, + merges.count * sizeof(*merges.keys)); + + for (i = 0; i < merges.count; ++i) + svn_temp_serializer__add_string(context, &merges.keys[i]); + + svn_temp_serializer__pop(context); + + /* key lengths array */ + svn_temp_serializer__push(context, + (const void * const *)&merges.key_lengths, + merges.count * sizeof(*merges.key_lengths)); + svn_temp_serializer__pop(context); + + /* range counts array */ + svn_temp_serializer__push(context, + (const void * const *)&merges.range_counts, + merges.count * sizeof(*merges.range_counts)); + svn_temp_serializer__pop(context); + + /* ranges */ + svn_temp_serializer__push(context, + (const void * const *)&merges.ranges, + range_count * sizeof(*merges.ranges)); + svn_temp_serializer__pop(context); + + /* return the serialized result */ + serialized = svn_temp_serializer__get(context); + + *data = serialized->data; + *data_len = serialized->len; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_fs__deserialize_mergeinfo(void **out, + void *data, + apr_size_t data_len, + apr_pool_t *pool) +{ + unsigned i; + int k, n; + mergeinfo_data_t *merges = (mergeinfo_data_t *)data; + svn_mergeinfo_t mergeinfo; + + /* de-serialize our auxiliary data structure */ + svn_temp_deserializer__resolve(merges, (void**)&merges->keys); + svn_temp_deserializer__resolve(merges, (void**)&merges->key_lengths); + svn_temp_deserializer__resolve(merges, (void**)&merges->range_counts); + svn_temp_deserializer__resolve(merges, (void**)&merges->ranges); + + /* de-serialize keys and add entries to the result */ + n = 0; + mergeinfo = svn_hash__make(pool); + for (i = 0; i < merges->count; ++i) + { + svn_rangelist_t *ranges = apr_array_make(pool, + merges->range_counts[i], + sizeof(svn_merge_range_t*)); + for (k = 0; k < merges->range_counts[i]; ++k, ++n) + APR_ARRAY_PUSH(ranges, svn_merge_range_t*) = &merges->ranges[n]; + + svn_temp_deserializer__resolve((void*)merges->keys, + (void**)&merges->keys[i]); + apr_hash_set(mergeinfo, merges->keys[i], merges->key_lengths[i], ranges); + } + + /* done */ + *out = mergeinfo; + + return SVN_NO_ERROR; +} + |