121
121
return SVN_NO_ERROR;
124
/* Return a deep FS API type copy of SOURCE in internal format and allocate
125
* the result in RESULT_POOL.
127
static svn_fs_path_change2_t *
128
change_to_fs_change(const change_t *change,
129
apr_pool_t *result_pool)
131
svn_fs_path_change2_t *result = svn_fs__path_change_create_internal(
132
svn_fs_base__id_copy(change->noderev_id,
136
result->text_mod = change->text_mod;
137
result->prop_mod = change->prop_mod;
138
result->node_kind = svn_node_unknown;
139
result->copyfrom_known = FALSE;
125
144
/* Merge the internal-use-only CHANGE into a hash of public-FS
126
145
svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
127
146
single succinct change per path. */
128
147
static svn_error_t *
129
148
fold_change(apr_hash_t *changes,
149
apr_hash_t *deletions,
130
150
const change_t *change)
132
152
apr_pool_t *pool = apr_hash_pool_get(changes);
194
214
/* If the path was introduced in this transaction via an
195
215
add, and we are deleting it, just remove the path
219
else if (old_change->change_kind == svn_fs_path_change_replace)
221
/* A deleting a 'replace' restore the original deletion. */
222
new_change = svn_hash_gets(deletions, path);
223
SVN_ERR_ASSERT(new_change);
201
227
/* A deletion overrules all previous changes. */
202
old_change->change_kind = svn_fs_path_change_delete;
203
old_change->text_mod = change->text_mod;
204
old_change->prop_mod = change->prop_mod;
228
new_change = old_change;
229
new_change->change_kind = svn_fs_path_change_delete;
230
new_change->text_mod = change->text_mod;
231
new_change->prop_mod = change->prop_mod;
209
236
case svn_fs_path_change_replace:
210
237
/* An add at this point must be following a previous delete,
211
238
so treat it just like a replace. */
212
old_change->change_kind = svn_fs_path_change_replace;
213
old_change->node_rev_id = svn_fs_base__id_copy(change->noderev_id,
215
old_change->text_mod = change->text_mod;
216
old_change->prop_mod = change->prop_mod;
240
new_change = change_to_fs_change(change, pool);
241
new_change->change_kind = svn_fs_path_change_replace;
243
/* Remember the original deletion.
244
* Make sure to allocate the hash key in a durable pool. */
245
svn_hash_sets(deletions,
246
apr_pstrdup(apr_hash_pool_get(deletions), path),
219
250
case svn_fs_path_change_modify:
252
new_change = old_change;
221
253
if (change->text_mod)
222
old_change->text_mod = TRUE;
254
new_change->text_mod = TRUE;
223
255
if (change->prop_mod)
224
old_change->prop_mod = TRUE;
256
new_change->prop_mod = TRUE;
228
/* Point our new_change to our (possibly modified) old_change. */
229
new_change = old_change;
233
262
/* This change is new to the hash, so make a new public change
234
263
structure from the internal one (in the hash's pool), and dup
235
264
the path into the hash's pool, too. */
236
new_change = svn_fs__path_change_create_internal(
237
svn_fs_base__id_copy(change->noderev_id, pool),
240
new_change->text_mod = change->text_mod;
241
new_change->prop_mod = change->prop_mod;
242
new_change->node_kind = svn_node_unknown;
243
new_change->copyfrom_known = FALSE;
265
new_change = change_to_fs_change(change, pool);
244
266
path = apr_pstrdup(pool, change->path);
265
287
svn_error_t *err = SVN_NO_ERROR;
266
288
apr_hash_t *changes = apr_hash_make(pool);
267
289
apr_pool_t *subpool = svn_pool_create(pool);
290
apr_pool_t *iterpool = svn_pool_create(pool);
291
apr_hash_t *deletions = apr_hash_make(subpool);
269
293
/* Get a cursor on the first record matching KEY, and then loop over
270
294
the records, adding them to the return array. */
286
310
svn_skel_t *result_skel;
288
312
/* Clear the per-iteration subpool. */
289
svn_pool_clear(subpool);
313
svn_pool_clear(iterpool);
291
315
/* RESULT now contains a change record associated with KEY. We
292
316
need to parse that skel into an change_t structure ... */
293
result_skel = svn_skel__parse(result.data, result.size, subpool);
317
result_skel = svn_skel__parse(result.data, result.size, iterpool);
294
318
if (! result_skel)
296
320
err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
301
err = svn_fs_base__parse_change_skel(&change, result_skel, subpool);
325
err = svn_fs_base__parse_change_skel(&change, result_skel, iterpool);
305
329
/* ... and merge it with our return hash. */
306
err = fold_change(changes, change);
330
err = fold_change(changes, deletions, change);
349
373
/* Destroy the per-iteration subpool. */
374
svn_pool_destroy(iterpool);
350
375
svn_pool_destroy(subpool);
352
377
/* If there are no (more) change records for this KEY, we're