88
89
return queue->pool;
93
/*** Finishing updates and commits. ***/
95
/* Queue work items that will finish a commit of the file or directory
96
* LOCAL_ABSPATH in DB:
97
* - queue the removal of any "revert-base" props and text files;
98
* - queue an update of the DB entry for this node
100
* ### The Pristine Store equivalent should be:
101
* - remember the old BASE_NODE and WORKING_NODE pristine text c'sums;
102
* - queue an update of the DB entry for this node (incl. updating the
103
* BASE_NODE c'sum and setting the WORKING_NODE c'sum to NULL);
104
* - queue deletion of the old pristine texts by the remembered checksums.
106
* CHECKSUM is the checksum of the new text base for LOCAL_ABSPATH, and must
107
* be provided if there is one, else NULL.
109
* STATUS, KIND, PROP_MODS and OLD_CHECKSUM are the current in-db values of
110
* the node LOCAL_ABSPATH.
113
process_committed_leaf(svn_wc__db_t *db,
114
const char *local_abspath,
115
svn_boolean_t via_recurse,
116
svn_wc__db_status_t status,
117
svn_node_kind_t kind,
118
svn_boolean_t prop_mods,
119
const svn_checksum_t *old_checksum,
120
svn_revnum_t new_revnum,
121
apr_time_t new_changed_date,
122
const char *new_changed_author,
123
apr_hash_t *new_dav_cache,
124
svn_boolean_t no_unlock,
125
svn_boolean_t keep_changelist,
126
const svn_checksum_t *checksum,
127
apr_pool_t *scratch_pool)
129
svn_revnum_t new_changed_rev = new_revnum;
130
svn_skel_t *work_item = NULL;
132
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
135
const char *adm_abspath;
137
if (kind == svn_node_dir)
138
adm_abspath = local_abspath;
140
adm_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
141
SVN_ERR(svn_wc__write_check(db, adm_abspath, scratch_pool));
144
if (status == svn_wc__db_status_deleted)
146
return svn_error_trace(
147
svn_wc__db_base_remove(
149
FALSE /* keep_as_working */,
150
FALSE /* queue_deletes */,
151
TRUE /* remove_locks */,
153
? new_revnum : SVN_INVALID_REVNUM,
157
else if (status == svn_wc__db_status_not_present)
159
/* We are committing the leaf of a copy operation.
160
We leave the not-present marker to allow pulling in excluded
163
The next update will remove the not-present marker. */
168
SVN_ERR_ASSERT(status == svn_wc__db_status_normal
169
|| status == svn_wc__db_status_incomplete
170
|| status == svn_wc__db_status_added);
172
if (kind != svn_node_dir)
174
/* If we sent a delta (meaning: post-copy modification),
175
then this file will appear in the queue and so we should have
176
its checksum already. */
177
if (checksum == NULL)
179
/* It was copied and not modified. We must have a text
180
base for it. And the node should have a checksum. */
181
SVN_ERR_ASSERT(old_checksum != NULL);
183
checksum = old_checksum;
185
/* Is the node completely unmodified and are we recursing? */
186
if (via_recurse && !prop_mods)
188
/* If a copied node itself is not modified, but the op_root of
189
the copy is committed we have to make sure that changed_rev,
190
changed_date and changed_author don't change or the working
191
copy used for committing will show different last modified
192
information then a clean checkout of exactly the same
193
revisions. (Issue #3676) */
195
SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL,
196
NULL, &new_changed_rev,
198
&new_changed_author, NULL, NULL,
199
NULL, NULL, NULL, NULL, NULL,
200
NULL, NULL, NULL, NULL,
201
NULL, NULL, NULL, NULL,
204
scratch_pool, scratch_pool));
208
SVN_ERR(svn_wc__wq_build_file_commit(&work_item,
211
scratch_pool, scratch_pool));
214
/* The new text base will be found in the pristine store by its checksum. */
215
SVN_ERR(svn_wc__db_global_commit(db, local_abspath,
216
new_revnum, new_changed_rev,
217
new_changed_date, new_changed_author,
219
NULL /* new_children */,
231
svn_wc__process_committed_internal(svn_wc__db_t *db,
232
const char *local_abspath,
233
svn_boolean_t recurse,
234
svn_boolean_t top_of_recurse,
235
svn_revnum_t new_revnum,
237
const char *rev_author,
238
apr_hash_t *new_dav_cache,
239
svn_boolean_t no_unlock,
240
svn_boolean_t keep_changelist,
241
const svn_checksum_t *sha1_checksum,
242
const svn_wc_committed_queue_t *queue,
243
apr_pool_t *scratch_pool)
245
svn_wc__db_status_t status;
246
svn_node_kind_t kind;
247
const svn_checksum_t *old_checksum;
248
svn_boolean_t prop_mods;
250
SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
251
NULL, NULL, NULL, &old_checksum, NULL, NULL,
252
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
253
NULL, NULL, &prop_mods, NULL, NULL, NULL,
255
scratch_pool, scratch_pool));
257
/* NOTE: be wary of making crazy semantic changes in this function, since
258
svn_wc_process_committed4() calls this. */
260
SVN_ERR(process_committed_leaf(db, local_abspath, !top_of_recurse,
261
status, kind, prop_mods, old_checksum,
262
new_revnum, new_date, rev_author,
264
no_unlock, keep_changelist,
268
/* Only check for recursion on nodes that have children */
269
if (kind != svn_node_file
270
|| status == svn_wc__db_status_not_present
271
|| status == svn_wc__db_status_excluded
272
|| status == svn_wc__db_status_server_excluded
273
/* Node deleted -> then no longer a directory */
274
|| status == svn_wc__db_status_deleted)
281
const apr_array_header_t *children;
282
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
285
/* Read PATH's entries; this is the absolute path. */
286
SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
287
scratch_pool, iterpool));
289
/* Recursively loop over all children. */
290
for (i = 0; i < children->nelts; i++)
292
const char *name = APR_ARRAY_IDX(children, i, const char *);
293
const char *this_abspath;
294
const committed_queue_item_t *cqi;
296
svn_pool_clear(iterpool);
298
this_abspath = svn_dirent_join(local_abspath, name, iterpool);
300
sha1_checksum = NULL;
301
cqi = svn_hash_gets(queue->queue, this_abspath);
304
sha1_checksum = cqi->sha1_checksum;
306
/* Recurse. Pass NULL for NEW_DAV_CACHE, because the
307
ones present in the current call are only applicable to
308
this one committed item. */
309
SVN_ERR(svn_wc__process_committed_internal(
312
FALSE /* top_of_recurse */,
313
new_revnum, new_date,
315
NULL /* new_dav_cache */,
316
TRUE /* no_unlock */,
323
svn_pool_destroy(iterpool);
331
93
svn_wc__prop_array_to_hash(const apr_array_header_t *props,
332
94
apr_pool_t *result_pool)
358
120
q = apr_palloc(pool, sizeof(*q));
360
q->queue = apr_hash_make(pool);
361
q->have_recursive = FALSE;
122
q->wc_queues = apr_hash_make(pool);
368
svn_wc_queue_committed3(svn_wc_committed_queue_t *queue,
129
svn_wc_queue_committed4(svn_wc_committed_queue_t *queue,
369
130
svn_wc_context_t *wc_ctx,
370
131
const char *local_abspath,
371
132
svn_boolean_t recurse,
133
svn_boolean_t is_committed,
372
134
const apr_array_header_t *wcprop_changes,
373
135
svn_boolean_t remove_lock,
374
136
svn_boolean_t remove_changelist,
375
137
const svn_checksum_t *sha1_checksum,
376
138
apr_pool_t *scratch_pool)
378
committed_queue_item_t *cqi;
140
const char *wcroot_abspath;
141
svn_wc__db_commit_queue_t *db_queue;
380
143
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
382
queue->have_recursive |= recurse;
384
145
/* Use the same pool as the one QUEUE was allocated in,
385
146
to prevent lifetime issues. Intermediate operations
386
147
should use SCRATCH_POOL. */
388
/* Add to the array with paths and options */
389
cqi = apr_palloc(queue->pool, sizeof(*cqi));
390
cqi->local_abspath = local_abspath;
391
cqi->recurse = recurse;
392
cqi->no_unlock = !remove_lock;
393
cqi->keep_changelist = !remove_changelist;
394
cqi->sha1_checksum = sha1_checksum;
395
cqi->new_dav_cache = svn_wc__prop_array_to_hash(wcprop_changes, queue->pool);
397
svn_hash_sets(queue->queue, local_abspath, cqi);
403
/* Return TRUE if any item of QUEUE is a parent of ITEM and will be
404
processed recursively, return FALSE otherwise.
406
The algorithmic complexity of this search implementation is O(queue
407
length), but it's quite quick.
410
have_recursive_parent(apr_hash_t *queue,
411
const committed_queue_item_t *item,
412
apr_pool_t *scratch_pool)
414
apr_hash_index_t *hi;
415
const char *local_abspath = item->local_abspath;
417
for (hi = apr_hash_first(scratch_pool, queue); hi; hi = apr_hash_next(hi))
149
SVN_ERR(svn_wc__db_get_wcroot(&wcroot_abspath,
150
wc_ctx->db, local_abspath,
151
scratch_pool, scratch_pool));
153
db_queue = svn_hash_gets(queue->wc_queues, wcroot_abspath);
419
const committed_queue_item_t *qi = svn__apr_hash_index_val(hi);
424
if (qi->recurse && svn_dirent_is_child(qi->local_abspath, local_abspath,
156
wcroot_abspath = apr_pstrdup(queue->pool, wcroot_abspath);
158
SVN_ERR(svn_wc__db_create_commit_queue(&db_queue,
159
wc_ctx->db, wcroot_abspath,
160
queue->pool, scratch_pool));
162
svn_hash_sets(queue->wc_queues, wcroot_abspath, db_queue);
165
return svn_error_trace(
166
svn_wc__db_commit_queue_add(db_queue, local_abspath, recurse,
167
is_committed, remove_lock,
168
remove_changelist, sha1_checksum,
169
svn_wc__prop_array_to_hash(wcprop_changes,
171
queue->pool, scratch_pool));
440
182
void *cancel_baton,
441
183
apr_pool_t *scratch_pool)
443
apr_array_header_t *sorted_queue;
185
apr_array_header_t *wcs;
445
187
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
446
188
apr_time_t new_date;
447
apr_hash_t *run_wqs = apr_hash_make(scratch_pool);
448
apr_hash_index_t *hi;
451
191
SVN_ERR(svn_time_from_cstring(&new_date, rev_date, iterpool));
455
/* Process the queued items in order of their paths. (The requirement is
456
* probably just that a directory must be processed before its children.) */
457
sorted_queue = svn_sort__hash(queue->queue, svn_sort_compare_items_as_paths,
459
for (i = 0; i < sorted_queue->nelts; i++)
195
/* Process the wc's in order of their paths. */
196
wcs = svn_sort__hash(queue->wc_queues, svn_sort_compare_items_as_paths,
198
for (i = 0; i < wcs->nelts; i++)
461
200
const svn_sort__item_t *sort_item
462
= &APR_ARRAY_IDX(sorted_queue, i, svn_sort__item_t);
463
const committed_queue_item_t *cqi = sort_item->value;
464
const char *wcroot_abspath;
201
= &APR_ARRAY_IDX(wcs, i, svn_sort__item_t);
202
svn_wc__db_commit_queue_t *db_queue = sort_item->value;
466
204
svn_pool_clear(iterpool);
468
/* Skip this item if it is a child of a recursive item, because it has
469
been (or will be) accounted for when that recursive item was (or
470
will be) processed. */
471
if (queue->have_recursive && have_recursive_parent(queue->queue, cqi,
475
SVN_ERR(svn_wc__process_committed_internal(
476
wc_ctx->db, cqi->local_abspath,
478
TRUE /* top_of_recurse */,
479
new_revnum, new_date, rev_author,
482
cqi->keep_changelist,
483
cqi->sha1_checksum, queue,
486
/* Don't run the wq now, but remember that we must call it for this
488
SVN_ERR(svn_wc__db_get_wcroot(&wcroot_abspath,
489
wc_ctx->db, cqi->local_abspath,
490
iterpool, iterpool));
492
if (! svn_hash_gets(run_wqs, wcroot_abspath))
494
wcroot_abspath = apr_pstrdup(scratch_pool, wcroot_abspath);
495
svn_hash_sets(run_wqs, wcroot_abspath, wcroot_abspath);
206
SVN_ERR(svn_wc__db_process_commit_queue(wc_ctx->db, db_queue,
207
new_revnum, new_date, rev_author,
499
211
/* Make sure nothing happens if this function is called again. */
500
apr_hash_clear(queue->queue);
212
apr_hash_clear(queue->wc_queues);
502
214
/* Ok; everything is committed now. Now we can start calling callbacks */
505
216
SVN_ERR(cancel_func(cancel_baton));
507
for (hi = apr_hash_first(scratch_pool, run_wqs);
509
hi = apr_hash_next(hi))
218
for (i = 0; i < wcs->nelts; i++)
511
const char *wcroot_abspath = svn__apr_hash_index_key(hi);
220
const svn_sort__item_t *sort_item
221
= &APR_ARRAY_IDX(wcs, i, svn_sort__item_t);
222
const char *wcroot_abspath = sort_item->key;
513
224
svn_pool_clear(iterpool);