Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/commit_util.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/commit_util.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_client/commit_util.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_client/commit_util.c Sun Feb 22 16:52:05 2015 @@ -467,10 +467,12 @@ harvest_not_present_for_copy(svn_wc_cont apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; + SVN_ERR_ASSERT(commit_relpath != NULL); + /* A function to retrieve not present children would be nice to have */ - SVN_ERR(svn_wc__node_get_children_of_working_node( - &children, wc_ctx, local_abspath, TRUE, - scratch_pool, iterpool)); + SVN_ERR(svn_wc__node_get_not_present_children(&children, wc_ctx, + local_abspath, + scratch_pool, iterpool)); for (i = 0; i < children->nelts; i++) { @@ -486,13 +488,10 @@ harvest_not_present_for_copy(svn_wc_cont this_abspath, FALSE, scratch_pool)); if (!not_present) - continue; + continue; /* Node is replaced */ - if (commit_relpath == NULL) - this_commit_relpath = NULL; - else - this_commit_relpath = svn_relpath_join(commit_relpath, name, - iterpool); + this_commit_relpath = svn_relpath_join(commit_relpath, name, + iterpool); /* We should check if we should really add a delete operation */ if (check_url_func) @@ -1380,7 +1379,10 @@ svn_client__get_copy_committables(svn_cl } -int svn_client__sort_commit_item_urls(const void *a, const void *b) +/* A svn_sort__array()/qsort()-compatible sort routine for sorting + an array of svn_client_commit_item_t *'s by their URL member. */ +static int +sort_commit_item_urls(const void *a, const void *b) { const svn_client_commit_item3_t *item1 = *((const svn_client_commit_item3_t * const *) a); @@ -1404,7 +1406,7 @@ svn_client__condense_commit_items(const SVN_ERR_ASSERT(ci && ci->nelts); /* Sort our commit items by their URLs. */ - svn_sort__array(ci, svn_client__sort_commit_item_urls); + svn_sort__array(ci, sort_commit_item_urls); /* Loop through the URLs, finding the longest usable ancestor common to all of them, and making sure there are no duplicate URLs. */
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c Sun Feb 22 16:52:05 2015 @@ -3093,6 +3093,7 @@ svn_client_copy7(const apr_array_header_ svn_boolean_t copy_as_child, svn_boolean_t make_parents, svn_boolean_t ignore_externals, + svn_boolean_t metadata_only, svn_boolean_t pin_externals, const apr_hash_t *externals_to_pin, const apr_hash_t *revprop_table, @@ -3113,7 +3114,7 @@ svn_client_copy7(const apr_array_header_ sources, dst_path, FALSE /* is_move */, TRUE /* allow_mixed_revisions */, - FALSE /* metadata_only */, + metadata_only, make_parents, ignore_externals, pin_externals, @@ -3149,7 +3150,7 @@ svn_client_copy7(const apr_array_header_ sources, dst_path, FALSE /* is_move */, TRUE /* allow_mixed_revisions */, - FALSE /* metadata_only */, + metadata_only, make_parents, ignore_externals, pin_externals, Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/deprecated.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_client/deprecated.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_client/deprecated.c Sun Feb 22 16:52:05 2015 @@ -640,7 +640,10 @@ svn_client_copy6(const apr_array_header_ { return svn_error_trace(svn_client_copy7(sources, dst_path, copy_as_child, make_parents, ignore_externals, - FALSE, NULL, revprop_table, + FALSE /* metadata_only */, + FALSE /* pin_externals */, + NULL /* externals_to_pin */, + revprop_table, commit_callback, commit_baton, ctx, pool)); } Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_client/merge.c Sun Feb 22 16:52:05 2015 @@ -6131,8 +6131,9 @@ insert_parent_and_sibs_of_sw_absent_del_ } /*(parent == NULL) */ /* Add all of PARENT's non-missing children that are not already present.*/ - SVN_ERR(svn_wc__node_get_children(&children, ctx->wc_ctx, - parent_abspath, FALSE, pool, pool)); + SVN_ERR(svn_wc__node_get_children_of_working_node(&children, ctx->wc_ctx, + parent_abspath, + pool, pool)); iterpool = svn_pool_create(pool); for (i = 0; i < children->nelts; i++) { @@ -6614,7 +6615,7 @@ get_mergeinfo_paths(apr_array_header_t * SVN_ERR(svn_wc__node_get_children_of_working_node( &immediate_children, ctx->wc_ctx, - target->abspath, FALSE, scratch_pool, scratch_pool)); + target->abspath, scratch_pool, scratch_pool)); for (j = 0; j < immediate_children->nelts; j++) { @@ -6698,9 +6699,10 @@ get_mergeinfo_paths(apr_array_header_t * const apr_array_header_t *children; int j; - SVN_ERR(svn_wc__node_get_children(&children, + SVN_ERR(svn_wc__node_get_children_of_working_node( + &children, ctx->wc_ctx, - child->abspath, FALSE, + child->abspath, iterpool, iterpool)); for (j = 0; j < children->nelts; j++) { Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c Sun Feb 22 16:52:05 2015 @@ -326,7 +326,8 @@ obtain_eol_and_keywords_for_file(apr_has const char *rev_str; const char *author; const char *url; - const char *root_url; + const char *repos_root_url; + const char *repos_relpath; SVN_ERR(svn_wc__node_get_changed_info(&changed_rev, &changed_date, @@ -335,15 +336,17 @@ obtain_eol_and_keywords_for_file(apr_has scratch_pool, scratch_pool)); rev_str = apr_psprintf(scratch_pool, "%ld", changed_rev); - SVN_ERR(svn_wc__node_get_url(&url, wc_ctx, - local_abspath, - scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL, &root_url, NULL, + SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath, &repos_root_url, + NULL, wc_ctx, local_abspath, scratch_pool, scratch_pool)); + url = svn_path_url_add_component2(repos_root_url, repos_relpath, + scratch_pool); + SVN_ERR(svn_subst_build_keywords3(keywords, keywords_val->data, - rev_str, url, root_url, changed_date, + rev_str, url, repos_root_url, + changed_date, author, result_pool)); } @@ -1592,7 +1595,7 @@ static svn_error_t * get_hunk_info(hunk_info_t **hi, patch_target_t *target, target_content_t *content, svn_diff_hunk_t *hunk, svn_linenum_t fuzz, - apr_int64_t previous_offset, + svn_linenum_t previous_offset, svn_boolean_t ignore_whitespace, svn_boolean_t is_prop_hunk, svn_cancel_func_t cancel_func, void *cancel_baton, @@ -2272,7 +2275,7 @@ apply_one_patch(patch_target_t **patch_t int i; static const svn_linenum_t MAX_FUZZ = 2; apr_hash_index_t *hash_index; - apr_int64_t previous_offset = 0; + svn_linenum_t previous_offset = 0; SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count, remove_tempfiles, result_pool, scratch_pool)); Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c Sun Feb 22 16:52:05 2015 @@ -1497,7 +1497,7 @@ svn_error_t *svn_ra_get_file_revs2(svn_r if (include_merged_revisions) SVN_ERR(svn_ra__assert_mergeinfo_capable_server(session, NULL, pool)); - if (start > end) + if (start > end || !SVN_IS_VALID_REVNUM(start)) SVN_ERR( svn_ra__assert_capable_server(session, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE, @@ -1507,7 +1507,8 @@ svn_error_t *svn_ra_get_file_revs2(svn_r err = session->vtable->get_file_revs(session, path, start, end, include_merged_revisions, handler, handler_baton, pool); - if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)) + if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED) + && !include_merged_revisions) { svn_error_clear(err); @@ -1515,7 +1516,7 @@ svn_error_t *svn_ra_get_file_revs2(svn_r err = svn_ra__file_revs_from_log(session, path, start, end, handler, handler_baton, pool); } - return err; + return svn_error_trace(err); } svn_error_t *svn_ra_lock(svn_ra_session_t *session, Modified: subversion/branches/move-tracking-2/subversion/libsvn_repos/load-fs-vtable.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_repos/load-fs-vtable.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_repos/load-fs-vtable.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_repos/load-fs-vtable.c Sun Feb 22 16:52:05 2015 @@ -726,6 +726,7 @@ set_revision_property(void *baton, struct revision_baton *rb = baton; struct parse_baton *pb = rb->pb; svn_boolean_t is_date = strcmp(name, SVN_PROP_REVISION_DATE) == 0; + svn_prop_t *prop; /* If we're skipping this revision, we're done here. */ if (rb->skipped) @@ -735,32 +736,16 @@ set_revision_property(void *baton, if (is_date && pb->ignore_dates) return SVN_NO_ERROR; - if (rb->rev > 0) - { - svn_prop_t *prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t); - - /* Collect property changes to apply them in one FS call in - close_revision. */ - prop->name = apr_pstrdup(rb->pool, name); - prop->value = svn_string_dup(value, rb->pool); - - /* Remember any datestamp that passes through! (See comment in - close_revision() below.) */ - if (is_date) - rb->datestamp = svn_string_dup(value, rb->pool); - } - else if (rb->rev == 0) - { - /* Special case: set revision 0 properties when loading into an - 'empty' filesystem. */ - svn_revnum_t youngest_rev; - - SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, rb->pool)); - - if (youngest_rev == 0) - SVN_ERR(change_rev_prop(pb->repos, 0, name, value, - pb->validate_props, rb->pool)); - } + /* Collect property changes to apply them in one FS call in + close_revision. */ + prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t); + prop->name = apr_pstrdup(rb->pool, name); + prop->value = svn_string_dup(value, rb->pool); + + /* Remember any datestamp that passes through! (See comment in + close_revision() below.) */ + if (is_date) + rb->datestamp = svn_string_dup(value, rb->pool); return SVN_NO_ERROR; } @@ -1018,11 +1003,41 @@ close_revision(void *baton) const char *txn_name = NULL; apr_hash_t *hooks_env; - /* If we're skipping this revision or it has an invalid revision - number, we're done here. */ - if (rb->skipped || (rb->rev <= 0)) + /* If we're skipping this revision we're done here. */ + if (rb->skipped) return SVN_NO_ERROR; + if (rb->rev == 0) + { + /* Special case: set revision 0 properties when loading into an + 'empty' filesystem. */ + svn_revnum_t youngest_rev; + + SVN_ERR(svn_fs_youngest_rev(&youngest_rev, pb->fs, rb->pool)); + + if (youngest_rev == 0) + { + apr_hash_t *orig_props; + apr_hash_t *new_props; + apr_array_header_t *diff; + int i; + + SVN_ERR(svn_fs_revision_proplist(&orig_props, pb->fs, 0, rb->pool)); + new_props = svn_prop_array_to_hash(rb->revprops, rb->pool); + SVN_ERR(svn_prop_diffs(&diff, new_props, orig_props, rb->pool)); + + for (i = 0; i < diff->nelts; i++) + { + const svn_prop_t *prop = &APR_ARRAY_IDX(diff, i, svn_prop_t); + + SVN_ERR(change_rev_prop(pb->repos, 0, prop->name, prop->value, + pb->validate_props, rb->pool)); + } + } + + return SVN_NO_ERROR; + } + /* If the dumpstream doesn't have an 'svn:date' property and we aren't ignoring the dates in the dumpstream altogether, remove any 'svn:date' revision property that was set by FS layer when Modified: subversion/branches/move-tracking-2/subversion/libsvn_repos/rev_hunt.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_repos/rev_hunt.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_repos/rev_hunt.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_repos/rev_hunt.c Sun Feb 22 16:52:05 2015 @@ -1559,6 +1559,18 @@ svn_repos_get_file_revs2(svn_repos_t *re struct send_baton sb; int mainline_pos, merged_pos; + if (!SVN_IS_VALID_REVNUM(start) + || !SVN_IS_VALID_REVNUM(end)) + { + svn_revnum_t youngest_rev; + SVN_ERR(svn_fs_youngest_rev(&youngest_rev, repos->fs, scratch_pool)); + + if (!SVN_IS_VALID_REVNUM(start)) + start = youngest_rev; + if (!SVN_IS_VALID_REVNUM(end)) + end = youngest_rev; + } + if (end < start) { if (include_merged_revisions) Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c Sun Feb 22 16:52:05 2015 @@ -1819,6 +1819,61 @@ svn_cache__membuffer_cache_create(svn_me return SVN_NO_ERROR; } +svn_error_t * +svn_cache__membuffer_clear(svn_membuffer_t *cache) +{ + apr_size_t seg; + apr_size_t segment_count = cache->segment_count; + + /* Length of the group_initialized array in bytes. + See also svn_cache__membuffer_cache_create(). */ + apr_size_t group_init_size + = 1 + (cache->group_count + cache->spare_group_count) + / (8 * GROUP_INIT_GRANULARITY); + + /* Clear segment by segment. This implies that other thread may read + and write to other segments after we cleared them and before the + last segment is done. + + However, that is no different from a write request coming through + right after we cleared all segments because dependencies between + cache entries (recursive lookup / access locks) are not allowed. + */ + for (seg = 0; seg < segment_count; ++seg) + { + /* Unconditionally acquire the write lock. */ + SVN_ERR(force_write_lock_cache(&cache[seg])); + + /* Mark all groups as "not initialized", which implies "empty". */ + cache[seg].first_spare_group = NO_INDEX; + cache[seg].max_spare_used = 0; + + memset(cache[seg].group_initialized, 0, group_init_size); + + /* Unlink L1 contents. */ + cache[seg].l1.first = NO_INDEX; + cache[seg].l1.last = NO_INDEX; + cache[seg].l1.next = NO_INDEX; + cache[seg].l1.current_data = cache[seg].l1.start_offset; + + /* Unlink L2 contents. */ + cache[seg].l2.first = NO_INDEX; + cache[seg].l2.last = NO_INDEX; + cache[seg].l2.next = NO_INDEX; + cache[seg].l2.current_data = cache[seg].l2.start_offset; + + /* Reset content counters. */ + cache[seg].data_used = 0; + cache[seg].used_entries = 0; + + /* Segment may be used again. */ + SVN_ERR(unlock_cache(&cache[seg], SVN_NO_ERROR)); + } + + /* done here */ + return SVN_NO_ERROR; +} + /* Look for the cache entry in group GROUP_INDEX of CACHE, identified * by the hash value TO_FIND and set *FOUND accordingly. * Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/cache.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/cache.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_subr/cache.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_subr/cache.c Sun Feb 22 16:52:05 2015 @@ -102,6 +102,11 @@ svn_cache__has_key(svn_boolean_t *found, apr_pool_t *scratch_pool) { *found = FALSE; +#ifdef SVN_DEBUG + if (cache->pretend_empty) + return SVN_NO_ERROR; +#endif + return handle_error(cache, (cache->vtable->has_key)(found, cache->cache_internal, Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/sqlite.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/sqlite.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_subr/sqlite.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_subr/sqlite.c Sun Feb 22 16:52:05 2015 @@ -1477,8 +1477,6 @@ struct function_wrapper_baton_t { svn_sqlite__func_t func; void *baton; - - apr_pool_t *scratch_pool; }; static void @@ -1488,22 +1486,12 @@ wrapped_func(sqlite3_context *context, { struct function_wrapper_baton_t *fwb = sqlite3_user_data(context); svn_sqlite__context_t sctx; - svn_sqlite__value_t **local_vals = - apr_palloc(fwb->scratch_pool, - sizeof(svn_sqlite__value_t *) * argc); svn_error_t *err; - int i; + void *void_values = values; sctx.context = context; - for (i = 0; i < argc; i++) - { - local_vals[i] = apr_palloc(fwb->scratch_pool, sizeof(*local_vals[i])); - local_vals[i]->value = values[i]; - } - - err = fwb->func(&sctx, argc, local_vals, fwb->scratch_pool); - svn_pool_clear(fwb->scratch_pool); + err = fwb->func(&sctx, argc, void_values, fwb->baton); if (err) { @@ -1515,6 +1503,7 @@ wrapped_func(sqlite3_context *context, } } + svn_error_t * svn_sqlite__create_scalar_function(svn_sqlite__db_t *db, const char *func_name, @@ -1527,7 +1516,13 @@ svn_sqlite__create_scalar_function(svn_s struct function_wrapper_baton_t *fwb = apr_pcalloc(db->state_pool, sizeof(*fwb)); - fwb->scratch_pool = svn_pool_create(db->state_pool); + /* If we create our scratch pool in db->state pool it is cleared + before the database is closed. This breaks using queries + before we close the database :( + + We create a subpool in the global pool and only destroy it + when we want it to be destroyed */ + fwb->func = func; fwb->baton = baton; @@ -1545,13 +1540,15 @@ svn_sqlite__create_scalar_function(svn_s int svn_sqlite__value_type(svn_sqlite__value_t *val) { - return sqlite3_value_type(val->value); + void *v = val; + return sqlite3_value_type(v); } const char * svn_sqlite__value_text(svn_sqlite__value_t *val) { - return (const char *) sqlite3_value_text(val->value); + void *v = val; + return (const char *) sqlite3_value_text(v); } void Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/adm_ops.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/adm_ops.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/adm_ops.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/adm_ops.c Sun Feb 22 16:52:05 2015 @@ -680,7 +680,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx, repos_relpath, repos_root_url, repos_uuid, copyfrom_rev, - NULL /* children */, FALSE, depth, + NULL /* children */, depth, + FALSE /* is_move */, NULL /* conflicts */, NULL /* work items */, scratch_pool)); Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/copy.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/copy.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/copy.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/copy.c Sun Feb 22 16:52:05 2015 @@ -965,18 +965,18 @@ remove_node_conflict_markers(svn_wc__db_ { const char *marker_abspath; const char *child_relpath; - const char *child_abpath; + const char *child_abspath; marker_abspath = APR_ARRAY_IDX(markers, i, const char *); - child_relpath = svn_dirent_is_child(src_dir, marker_abspath, NULL); + child_relpath = svn_dirent_skip_ancestor(src_dir, marker_abspath); if (child_relpath) { - child_abpath = svn_dirent_join(dst_dir, child_relpath, - scratch_pool); + child_abspath = svn_dirent_join(dst_dir, child_relpath, + scratch_pool); - SVN_ERR(svn_io_remove_file2(child_abpath, TRUE, scratch_pool)); + SVN_ERR(svn_io_remove_file2(child_abspath, TRUE, scratch_pool)); } } } @@ -996,7 +996,9 @@ remove_node_conflict_markers(svn_wc__db_ static svn_error_t * remove_all_conflict_markers(svn_wc__db_t *db, const char *src_dir_abspath, - const char *wc_dir_abspath, + const char *dst_dir_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, apr_pool_t *scratch_pool) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); @@ -1020,13 +1022,16 @@ remove_all_conflict_markers(svn_wc__db_t const char *name = apr_hash_this_key(hi); struct svn_wc__db_info_t *info = apr_hash_this_val(hi); + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + if (info->conflicted) { svn_pool_clear(iterpool); SVN_ERR(remove_node_conflict_markers( db, svn_dirent_join(src_dir_abspath, name, iterpool), - svn_dirent_join(wc_dir_abspath, name, iterpool), + svn_dirent_join(dst_dir_abspath, name, iterpool), iterpool)); } if (info->kind == svn_node_dir) @@ -1035,7 +1040,8 @@ remove_all_conflict_markers(svn_wc__db_t SVN_ERR(remove_all_conflict_markers( db, svn_dirent_join(src_dir_abspath, name, iterpool), - svn_dirent_join(wc_dir_abspath, name, iterpool), + svn_dirent_join(dst_dir_abspath, name, iterpool), + cancel_func, cancel_baton, iterpool)); } } @@ -1093,7 +1099,25 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, is still in a valid state. So be careful when switching this over to the workqueue. */ if (!metadata_only) - SVN_ERR(svn_io_file_rename(src_abspath, dst_abspath, scratch_pool)); + { + svn_error_t *err; + + err = svn_error_trace(svn_io_file_rename(src_abspath, dst_abspath, + scratch_pool)); + + /* Let's try if we can keep wc.db consistent even when the move + fails. Deleting the target is a wc.db only operation, while + going forward (delaying the error) would try to change + conflict markers, which might also fail. */ + if (err) + return svn_error_trace( + svn_error_compose_create( + err, + svn_wc__db_op_delete(wc_ctx->db, dst_abspath, NULL, TRUE, + NULL, NULL, cancel_func, cancel_baton, + NULL, NULL, + scratch_pool))); + } SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1105,11 +1129,20 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, if (kind == svn_node_dir) SVN_ERR(remove_all_conflict_markers(db, src_abspath, dst_abspath, + cancel_func, cancel_baton, scratch_pool)); if (conflicted) - SVN_ERR(remove_node_conflict_markers(db, src_abspath, dst_abspath, - scratch_pool)); + { + /* When we moved a directory, we moved the conflict markers + with the target... if we moved a file we only moved the + file itself and the markers are still in the old location */ + SVN_ERR(remove_node_conflict_markers(db, src_abspath, + (kind == svn_node_dir) + ? dst_abspath + : src_abspath, + scratch_pool)); + } SVN_ERR(svn_wc__db_op_delete(db, src_abspath, record_on_delete ? dst_abspath : NULL, Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c Sun Feb 22 16:52:05 2015 @@ -1051,8 +1051,12 @@ svn_wc__diff_local_only_dir(svn_wc__db_t copyfrom_src->repos_relpath = original_repos_relpath; } + /* svn_wc__db_status_incomplete should never happen, as the result won't be + stable or guaranteed related to what is in the repository for this + revision, but without this it would be hard to diagnose that status... */ assert(kind == svn_node_dir && (status == svn_wc__db_status_normal + || status == svn_wc__db_status_incomplete || status == svn_wc__db_status_added || (status == svn_wc__db_status_deleted && diff_pristine))); @@ -1167,12 +1171,12 @@ svn_wc__diff_local_only_dir(svn_wc__db_t if (!skip) { apr_hash_t *right_props; - if (diff_pristine) - SVN_ERR(svn_wc__db_read_pristine_props(&right_props, db, local_abspath, - scratch_pool, scratch_pool)); + + if (props_mod && !diff_pristine) + SVN_ERR(svn_wc__db_read_props(&right_props, db, local_abspath, + scratch_pool, scratch_pool)); else - SVN_ERR(svn_wc__get_actual_props(&right_props, db, local_abspath, - scratch_pool, scratch_pool)); + right_props = svn_prop_hash_dup(pristine_props, scratch_pool); SVN_ERR(processor->dir_added(relpath, copyfrom_src, Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/entries.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/entries.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/entries.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/entries.c Sun Feb 22 16:52:05 2015 @@ -48,6 +48,7 @@ #include "svn_private_config.h" #include "private/svn_wc_private.h" #include "private/svn_sqlite.h" +#include "token-map.h" #define MAYBE_ALLOC(x,p) ((x) ? (x) : apr_pcalloc((p), sizeof(*(x)))) @@ -1452,23 +1453,31 @@ insert_node(svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; + svn_boolean_t present = (node->presence == svn_wc__db_status_normal + || node->presence == svn_wc__db_status_incomplete); SVN_ERR_ASSERT(node->op_depth > 0 || node->repos_relpath); SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isdsnnnnsnrisnnni", + SVN_ERR(svn_sqlite__bindf(stmt, "isdsnnnnsn", node->wc_id, node->local_relpath, node->op_depth, node->parent_relpath, /* Setting depth for files? */ - svn_depth_to_word(node->depth), - node->changed_rev, - node->changed_date, - node->changed_author, - node->recorded_time)); + (node->kind == svn_node_dir && present) + ? svn_depth_to_word(node->depth) + : NULL)); - if (node->repos_relpath) + if (present && node->repos_relpath) + { + SVN_ERR(svn_sqlite__bind_revnum(stmt, 11, node->changed_rev)); + SVN_ERR(svn_sqlite__bind_int64(stmt, 12, node->changed_date)); + SVN_ERR(svn_sqlite__bind_text(stmt, 13, node->changed_author)); + } + + if (node->repos_relpath + && node->presence != svn_wc__db_status_base_deleted) { SVN_ERR(svn_sqlite__bind_int64(stmt, 5, node->repos_id)); @@ -1477,26 +1486,14 @@ insert_node(svn_sqlite__db_t *sdb, SVN_ERR(svn_sqlite__bind_revnum(stmt, 7, node->revision)); } - if (node->presence == svn_wc__db_status_normal) - SVN_ERR(svn_sqlite__bind_text(stmt, 8, "normal")); - else if (node->presence == svn_wc__db_status_not_present) - SVN_ERR(svn_sqlite__bind_text(stmt, 8, "not-present")); - else if (node->presence == svn_wc__db_status_base_deleted) - SVN_ERR(svn_sqlite__bind_text(stmt, 8, "base-deleted")); - else if (node->presence == svn_wc__db_status_incomplete) - SVN_ERR(svn_sqlite__bind_text(stmt, 8, "incomplete")); - else if (node->presence == svn_wc__db_status_excluded) - SVN_ERR(svn_sqlite__bind_text(stmt, 8, "excluded")); - else if (node->presence == svn_wc__db_status_server_excluded) - SVN_ERR(svn_sqlite__bind_text(stmt, 8, "server-excluded")); + SVN_ERR(svn_sqlite__bind_token(stmt, 8, presence_map, node->presence)); if (node->kind == svn_node_none) SVN_ERR(svn_sqlite__bind_text(stmt, 10, "unknown")); else - SVN_ERR(svn_sqlite__bind_text(stmt, 10, - svn_node_kind_to_word(node->kind))); + SVN_ERR(svn_sqlite__bind_token(stmt, 10, kind_map, node->kind)); - if (node->kind == svn_node_file) + if (node->kind == svn_node_file && present) { if (!node->checksum && node->op_depth == 0 @@ -1510,19 +1507,25 @@ insert_node(svn_sqlite__db_t *sdb, SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, node->checksum, scratch_pool)); + + if (node->repos_relpath) + { + if (node->recorded_size != SVN_INVALID_FILESIZE) + SVN_ERR(svn_sqlite__bind_int64(stmt, 16, node->recorded_size)); + + SVN_ERR(svn_sqlite__bind_int64(stmt, 17, node->recorded_time)); + } } - if (node->properties) /* ### Never set, props done later */ + /* ### Never set, props done later */ + if (node->properties && present && node->repos_relpath) SVN_ERR(svn_sqlite__bind_properties(stmt, 15, node->properties, scratch_pool)); - if (node->recorded_size != SVN_INVALID_FILESIZE) - SVN_ERR(svn_sqlite__bind_int64(stmt, 16, node->recorded_size)); - if (node->file_external) SVN_ERR(svn_sqlite__bind_int(stmt, 20, 1)); - if (node->inherited_props) + if (node->inherited_props && present) SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, node->inherited_props, scratch_pool)); @@ -1801,6 +1804,10 @@ write_entry(struct write_baton **entry_n if (entry->copied) { + db_node_t *work = parent_node->work + ? parent_node->work + : parent_node->below_work; + if (entry->copyfrom_url) { working_node->repos_id = repos_id; @@ -1810,20 +1817,37 @@ write_entry(struct write_baton **entry_n working_node->revision = entry->copyfrom_rev; working_node->op_depth = svn_wc__db_op_depth_for_upgrade(local_relpath); + + if (work && work->repos_relpath + && work->repos_id == repos_id + && work->revision == entry->copyfrom_rev) + { + const char *name; + + name = svn_relpath_skip_ancestor(work->repos_relpath, + working_node->repos_relpath); + + if (name + && !strcmp(name, svn_relpath_basename(local_relpath, NULL))) + { + working_node->op_depth = work->op_depth; + } + } } - else if (parent_node->work && parent_node->work->repos_relpath) + else if (work && work->repos_relpath) { working_node->repos_id = repos_id; working_node->repos_relpath - = svn_relpath_join(parent_node->work->repos_relpath, + = svn_relpath_join(work->repos_relpath, svn_relpath_basename(local_relpath, NULL), result_pool); - working_node->revision = parent_node->work->revision; - working_node->op_depth = parent_node->work->op_depth; + working_node->revision = work->revision; + working_node->op_depth = work->op_depth; } else if (parent_node->below_work && parent_node->below_work->repos_relpath) { + /* Parent deleted, this not-present or similar */ working_node->repos_id = repos_id; working_node->repos_relpath = svn_relpath_join(parent_node->below_work->repos_relpath, @@ -1837,6 +1861,29 @@ write_entry(struct write_baton **entry_n _("No copyfrom URL for '%s'"), svn_dirent_local_style(local_relpath, scratch_pool)); + + if (work && work->op_depth != working_node->op_depth + && work->repos_relpath + && work->repos_id == working_node->repos_id + && work->presence == svn_wc__db_status_normal + && !below_working_node) + { + /* Introduce a not-present node! */ + below_working_node = MAYBE_ALLOC(below_working_node, scratch_pool); + + below_working_node->wc_id = wc_id; + below_working_node->op_depth = work->op_depth; + below_working_node->local_relpath = local_relpath; + below_working_node->parent_relpath = parent_relpath; + + below_working_node->presence = svn_wc__db_status_not_present; + below_working_node->repos_id = repos_id; + below_working_node->repos_relpath = working_node->local_relpath; + + SVN_ERR(insert_node(sdb, below_working_node, scratch_pool)); + + below_working_node = NULL; /* Don't write a present intermediate! */ + } } if (entry->conflict_old) @@ -1909,11 +1956,6 @@ write_entry(struct write_baton **entry_n WRITE_ENTRY_ASSERT(conflict->kind == svn_wc_conflict_kind_tree); - /* Fix dubious data stored by old clients, local adds don't have - a repository URL. */ - if (conflict->reason == svn_wc_conflict_reason_added) - conflict->src_left_version = NULL; - SVN_ERR(svn_wc__serialize_conflict(&new_skel, conflict, scratch_pool, scratch_pool)); @@ -2140,17 +2182,18 @@ write_entry(struct write_baton **entry_n below_working_node->presence = svn_wc__db_status_normal; below_working_node->kind = entry->kind; below_working_node->repos_id = work->repos_id; + below_working_node->revision = work->revision; /* This is just guessing. If the node below would have been switched or if it was updated to a different version, the guess would fail. But we don't have better information pre wc-ng :( */ if (work->repos_relpath) below_working_node->repos_relpath - = svn_relpath_join(work->repos_relpath, entry->name, + = svn_relpath_join(work->repos_relpath, + svn_relpath_basename(local_relpath, NULL), result_pool); else below_working_node->repos_relpath = NULL; - below_working_node->revision = parent_node->work->revision; /* The revert_base checksum isn't available in the entry structure, so the caller provides it. */ @@ -2294,6 +2337,11 @@ write_entry(struct write_baton **entry_n { working_node->op_depth = parent_node->work->op_depth; } + else if (working_node->presence == svn_wc__db_status_excluded + && parent_node->work) + { + working_node->op_depth = parent_node->work->op_depth; + } else if (!entry->copied) { working_node->op_depth @@ -2660,11 +2708,11 @@ svn_wc_walk_entries3(const char *path, svn_wc__db_t *db = svn_wc__adm_get_db(adm_access); svn_error_t *err; svn_node_kind_t kind; - svn_depth_t depth; + svn_wc__db_status_t status; SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); - err = svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, &depth, NULL, NULL, + err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -2683,7 +2731,9 @@ svn_wc_walk_entries3(const char *path, walk_baton, pool); } - if (kind == svn_node_file || depth == svn_depth_exclude) + if (kind == svn_node_file + || status == svn_wc__db_status_excluded + || status == svn_wc__db_status_server_excluded) { const svn_wc_entry_t *entry; @@ -2692,27 +2742,24 @@ svn_wc_walk_entries3(const char *path, ### we should not call handle_error for an error the *callback* ### gave us. let it deal with the problem before returning. */ - if (!show_hidden) - { - svn_boolean_t hidden; - SVN_ERR(svn_wc__db_node_hidden(&hidden, db, local_abspath, pool)); - - if (hidden) - { - /* The fool asked to walk a "hidden" node. Report the node as - unversioned. - - ### this is incorrect behavior. see depth_test 36. the walk - ### API will be revamped to avoid entry structures. we should - ### be able to solve the problem with the new API. (since we - ### shouldn't return a hidden entry here) */ - return walk_callbacks->handle_error( - path, svn_error_createf( - SVN_ERR_UNVERSIONED_RESOURCE, NULL, - _("'%s' is not under version control"), - svn_dirent_local_style(local_abspath, pool)), - walk_baton, pool); - } + if (!show_hidden + && (status == svn_wc__db_status_not_present + || status == svn_wc__db_status_excluded + || status == svn_wc__db_status_server_excluded)) + { + /* The fool asked to walk a "hidden" node. Report the node as + unversioned. + + ### this is incorrect behavior. see depth_test 36. the walk + ### API will be revamped to avoid entry structures. we should + ### be able to solve the problem with the new API. (since we + ### shouldn't return a hidden entry here) */ + return walk_callbacks->handle_error( + path, svn_error_createf( + SVN_ERR_UNVERSIONED_RESOURCE, NULL, + _("'%s' is not under version control"), + svn_dirent_local_style(local_abspath, pool)), + walk_baton, pool); } SVN_ERR(svn_wc__get_entry(&entry, db, local_abspath, FALSE, Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/info.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/info.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/info.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/info.c Sun Feb 22 16:52:05 2015 @@ -141,7 +141,6 @@ build_info_for_node(svn_wc__info2_t **in { /* Root or child of copy */ tmpinfo->rev = original_revision; - repos_relpath = original_repos_relpath; if (op_root) { @@ -167,34 +166,6 @@ build_info_for_node(svn_wc__info2_t **in } } } - else if (op_root) - { - /* Local addition */ - SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath, - &tmpinfo->repos_root_URL, - &tmpinfo->repos_UUID, - NULL, NULL, NULL, NULL, - db, local_abspath, - result_pool, scratch_pool)); - - if (have_base) - SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &tmpinfo->rev, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, - db, local_abspath, - scratch_pool, scratch_pool)); - } - else - { - /* Child of copy. ### Not WC-NG like */ - SVN_ERR(svn_wc__internal_get_origin(NULL, &tmpinfo->rev, - &repos_relpath, - &tmpinfo->repos_root_URL, - &tmpinfo->repos_UUID, NULL, NULL, - db, local_abspath, TRUE, - result_pool, scratch_pool)); - } /* ### We should be able to avoid both these calls with the information from read_info() in most cases */ @@ -222,14 +193,20 @@ build_info_for_node(svn_wc__info2_t **in else wc_info->schedule = svn_wc_schedule_add; } - SVN_ERR(svn_wc__db_read_url(&tmpinfo->URL, db, local_abspath, - result_pool, scratch_pool)); + SVN_ERR(svn_wc__db_read_repos_info(NULL, &repos_relpath, + &tmpinfo->repos_root_URL, + &tmpinfo->repos_UUID, + db, local_abspath, + result_pool, scratch_pool)); + + tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, + repos_relpath, result_pool); } else if (status == svn_wc__db_status_deleted) { - const char *work_del_abspath; + svn_wc__db_status_t w_status; - SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, + SVN_ERR(svn_wc__db_read_pristine_info(&w_status, &tmpinfo->kind, &tmpinfo->last_changed_rev, &tmpinfo->last_changed_date, &tmpinfo->last_changed_author, @@ -239,51 +216,32 @@ build_info_for_node(svn_wc__info2_t **in db, local_abspath, result_pool, scratch_pool)); + if (w_status == svn_wc__db_status_deleted) + { + /* We have a working not-present status. We don't know anything + about this node, but it *is visible* in STATUS. + + Let's tell that it is excluded */ + + wc_info->depth = svn_depth_exclude; + tmpinfo->kind = svn_node_unknown; + } + /* And now fetch the url and revision of what will be deleted */ SVN_ERR(svn_wc__db_scan_deletion(NULL, &wc_info->moved_to_abspath, - &work_del_abspath, NULL, + NULL, NULL, db, local_abspath, scratch_pool, scratch_pool)); - if (work_del_abspath != NULL) - { - /* This is a deletion within a copied subtree. Get the copied-from - * revision. */ - const char *added_abspath = svn_dirent_dirname(work_del_abspath, - scratch_pool); - - SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath, - &tmpinfo->repos_root_URL, - &tmpinfo->repos_UUID, - NULL, NULL, NULL, - &tmpinfo->rev, - db, added_abspath, - result_pool, scratch_pool)); - - tmpinfo->URL = svn_path_url_add_component2( - tmpinfo->repos_root_URL, - svn_relpath_join(repos_relpath, - svn_dirent_skip_ancestor(added_abspath, - local_abspath), - scratch_pool), - result_pool); - } - else - { - SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, &tmpinfo->rev, - &repos_relpath, - &tmpinfo->repos_root_URL, - &tmpinfo->repos_UUID, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - db, local_abspath, - result_pool, scratch_pool)); - - tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, - repos_relpath, - result_pool); - } + + SVN_ERR(svn_wc__db_read_repos_info(&tmpinfo->rev, &repos_relpath, + &tmpinfo->repos_root_URL, + &tmpinfo->repos_UUID, + db, local_abspath, + result_pool, scratch_pool)); wc_info->schedule = svn_wc_schedule_delete; + tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, + repos_relpath, result_pool); } else if (status == svn_wc__db_status_not_present || status == svn_wc__db_status_server_excluded) @@ -291,6 +249,21 @@ build_info_for_node(svn_wc__info2_t **in *info = NULL; return SVN_NO_ERROR; } + else if (status == svn_wc__db_status_excluded && !repos_relpath) + { + /* We have a WORKING exclude. Avoid segfault on no repos info */ + + SVN_ERR(svn_wc__db_read_repos_info(NULL, &repos_relpath, + &tmpinfo->repos_root_URL, + &tmpinfo->repos_UUID, + db, local_abspath, + result_pool, scratch_pool)); + + wc_info->schedule = svn_wc_schedule_normal; + tmpinfo->URL = svn_path_url_add_component2(tmpinfo->repos_root_URL, + repos_relpath, result_pool); + tmpinfo->wc_info->depth = svn_depth_exclude; + } else { /* Just a BASE node. We have all the info we need */ @@ -298,10 +271,10 @@ build_info_for_node(svn_wc__info2_t **in repos_relpath, result_pool); wc_info->schedule = svn_wc_schedule_normal; - } - if (status == svn_wc__db_status_excluded) - tmpinfo->wc_info->depth = svn_depth_exclude; + if (status == svn_wc__db_status_excluded) + wc_info->depth = svn_depth_exclude; + } /* A default */ tmpinfo->size = SVN_INVALID_FILESIZE; @@ -544,15 +517,14 @@ svn_wc__get_info(svn_wc_context_t *wc_ct if (!repos_root_url) { - SVN_ERR(svn_wc__internal_get_repos_info(NULL, NULL, - &repos_root_url, - &repos_uuid, - wc_ctx->db, - svn_dirent_dirname( + SVN_ERR(svn_wc__db_read_repos_info(NULL, NULL, + &repos_root_url, + &repos_uuid, + wc_ctx->db, + svn_dirent_dirname( this_abspath, iterpool), - scratch_pool, - iterpool)); + scratch_pool, iterpool)); } info->repos_root_URL = repos_root_url; Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/node.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/node.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/node.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/node.c Sun Feb 22 16:52:05 2015 @@ -54,18 +54,14 @@ /* Set *CHILDREN_ABSPATHS to a new array of the full paths formed by joining - * each name in REL_CHILDREN onto DIR_ABSPATH. If SHOW_HIDDEN is false then - * omit any paths that are reported as 'hidden' by svn_wc__db_node_hidden(). + * each name in REL_CHILDREN onto DIR_ABSPATH. * * Allocate the output array and its elements in RESULT_POOL. */ -static svn_error_t * -filter_and_make_absolute(const apr_array_header_t **children_abspaths, - svn_wc_context_t *wc_ctx, - const char *dir_abspath, - const apr_array_header_t *rel_children, - svn_boolean_t show_hidden, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +static void +make_absolute(const apr_array_header_t **children_abspaths, + const char *dir_abspath, + const apr_array_header_t *rel_children, + apr_pool_t *result_pool) { apr_array_header_t *children; int i; @@ -74,29 +70,13 @@ filter_and_make_absolute(const apr_array sizeof(const char *)); for (i = 0; i < rel_children->nelts; i++) { - const char *child_abspath = svn_dirent_join(dir_abspath, - APR_ARRAY_IDX(rel_children, - i, - const char *), - result_pool); - - /* Don't add hidden nodes to *CHILDREN if we don't want them. */ - if (!show_hidden) - { - svn_boolean_t child_is_hidden; - - SVN_ERR(svn_wc__db_node_hidden(&child_is_hidden, wc_ctx->db, - child_abspath, scratch_pool)); - if (child_is_hidden) - continue; - } - - APR_ARRAY_PUSH(children, const char *) = child_abspath; + const char *name = APR_ARRAY_IDX(rel_children, i, const char *); + APR_ARRAY_PUSH(children, const char *) = + svn_dirent_join(dir_abspath, name, + result_pool); } *children_abspaths = children; - - return SVN_NO_ERROR; } @@ -104,136 +84,36 @@ svn_error_t * svn_wc__node_get_children_of_working_node(const apr_array_header_t **children, svn_wc_context_t *wc_ctx, const char *dir_abspath, - svn_boolean_t show_hidden, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - const apr_array_header_t *rel_children; + const apr_array_header_t *child_names; - SVN_ERR(svn_wc__db_read_children_of_working_node(&rel_children, + SVN_ERR(svn_wc__db_read_children_of_working_node(&child_names, wc_ctx->db, dir_abspath, scratch_pool, scratch_pool)); - SVN_ERR(filter_and_make_absolute(children, wc_ctx, dir_abspath, - rel_children, show_hidden, - result_pool, scratch_pool)); + make_absolute(children, dir_abspath, child_names, result_pool); return SVN_NO_ERROR; } - -svn_error_t * -svn_wc__node_get_children(const apr_array_header_t **children, - svn_wc_context_t *wc_ctx, - const char *dir_abspath, - svn_boolean_t show_hidden, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - const apr_array_header_t *rel_children; - - SVN_ERR(svn_wc__db_read_children(&rel_children, wc_ctx->db, dir_abspath, - scratch_pool, scratch_pool)); - SVN_ERR(filter_and_make_absolute(children, wc_ctx, dir_abspath, - rel_children, show_hidden, - result_pool, scratch_pool)); - return SVN_NO_ERROR; -} - svn_error_t * -svn_wc__internal_get_repos_info(svn_revnum_t *revision, - const char **repos_relpath, - const char **repos_root_url, - const char **repos_uuid, - svn_wc__db_t *db, - const char *local_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_wc__db_status_t status; - svn_boolean_t have_work; - - SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, repos_relpath, - repos_root_url, repos_uuid, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &have_work, - db, local_abspath, - result_pool, scratch_pool)); - - if ((repos_relpath ? *repos_relpath != NULL : TRUE) - && (repos_root_url ? *repos_root_url != NULL: TRUE) - && (repos_uuid ? *repos_uuid != NULL : TRUE)) - return SVN_NO_ERROR; /* We got the requested information */ - - if (!have_work) /* not-present, (server-)excluded? */ - { - return SVN_NO_ERROR; /* Can't fetch more */ - } - - if (status == svn_wc__db_status_deleted) - { - const char *base_del_abspath, *wrk_del_abspath; - - SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, NULL, - &wrk_del_abspath, NULL, - db, local_abspath, - scratch_pool, scratch_pool)); - - if (base_del_abspath) - { - SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, repos_relpath, - repos_root_url, repos_uuid, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, - db, base_del_abspath, - result_pool, scratch_pool)); - - /* If we have a repos_relpath, it is of the op-root */ - if (repos_relpath) - *repos_relpath = svn_relpath_join(*repos_relpath, - svn_dirent_skip_ancestor(base_del_abspath, - local_abspath), - result_pool); - /* We keep revision as SVN_INVALID_REVNUM */ - } - else if (wrk_del_abspath) - { - const char *op_root_abspath = NULL; - - SVN_ERR(svn_wc__db_scan_addition(NULL, repos_relpath - ? &op_root_abspath : NULL, - repos_relpath, repos_root_url, - repos_uuid, NULL, NULL, NULL, NULL, - db, svn_dirent_dirname( - wrk_del_abspath, - scratch_pool), - result_pool, scratch_pool)); - - /* If we have a repos_relpath, it is of the op-root */ - if (repos_relpath) - *repos_relpath = svn_relpath_join( - *repos_relpath, - svn_dirent_skip_ancestor(op_root_abspath, - local_abspath), - result_pool); - } - } - else /* added, or WORKING incomplete */ - { - /* We have an addition. scan_addition() will find the intended - repository location by scanning up the tree. */ - SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, - repos_relpath, repos_root_url, - repos_uuid, NULL, NULL, NULL, NULL, - db, local_abspath, - result_pool, scratch_pool)); - } - - SVN_ERR_ASSERT(repos_root_url == NULL || *repos_root_url != NULL); - SVN_ERR_ASSERT(repos_uuid == NULL || *repos_uuid != NULL); +svn_wc__node_get_not_present_children(const apr_array_header_t **children, + svn_wc_context_t *wc_ctx, + const char *dir_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const apr_array_header_t *child_names; + + SVN_ERR(svn_wc__db_base_read_not_present_children( + &child_names, + wc_ctx->db, dir_abspath, + scratch_pool, scratch_pool)); + make_absolute(children, dir_abspath, child_names, result_pool); return SVN_NO_ERROR; } + svn_error_t * svn_wc__node_get_repos_info(svn_revnum_t *revision, const char **repos_relpath, @@ -245,12 +125,12 @@ svn_wc__node_get_repos_info(svn_revnum_t apr_pool_t *scratch_pool) { return svn_error_trace( - svn_wc__internal_get_repos_info(revision, - repos_relpath, - repos_root_url, - repos_uuid, - wc_ctx->db, local_abspath, - result_pool, scratch_pool)); + svn_wc__db_read_repos_info(revision, + repos_relpath, + repos_root_url, + repos_uuid, + wc_ctx->db, local_abspath, + result_pool, scratch_pool)); } /* Convert DB_KIND into the appropriate NODE_KIND value. @@ -344,8 +224,18 @@ svn_wc__node_get_url(const char **url, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - return svn_error_trace(svn_wc__db_read_url(url, wc_ctx->db, local_abspath, - result_pool, scratch_pool)); + const char *repos_root_url; + const char *repos_relpath; + + SVN_ERR(svn_wc__db_read_repos_info(NULL, &repos_relpath, &repos_root_url, + NULL, + wc_ctx->db, local_abspath, + scratch_pool, scratch_pool)); + + *url = svn_path_url_add_component2(repos_root_url, repos_relpath, + result_pool); + + return SVN_NO_ERROR; } /* A recursive node-walker, helper for svn_wc__internal_walk_children(). @@ -517,33 +407,6 @@ svn_wc__internal_walk_children(svn_wc__d } svn_error_t * -svn_wc__node_get_deleted_ancestor(const char **deleted_ancestor_abspath, - svn_wc_context_t *wc_ctx, - const char *local_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_wc__db_status_t status; - - *deleted_ancestor_abspath = NULL; - - SVN_ERR(svn_wc__db_read_info(&status, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - wc_ctx->db, local_abspath, - scratch_pool, scratch_pool)); - - if (status == svn_wc__db_status_deleted) - SVN_ERR(svn_wc__db_scan_deletion(deleted_ancestor_abspath, NULL, NULL, - NULL, wc_ctx->db, local_abspath, - result_pool, scratch_pool)); - - return SVN_NO_ERROR; -} - -svn_error_t * svn_wc__node_is_not_present(svn_boolean_t *is_not_present, svn_boolean_t *is_excluded, svn_boolean_t *is_server_excluded, Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/translate.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/translate.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/translate.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/translate.c Sun Feb 22 16:52:05 2015 @@ -316,12 +316,15 @@ svn_wc__expand_keywords(apr_hash_t **key db, local_abspath, scratch_pool, scratch_pool)); - if (repos_relpath) - url = svn_path_url_add_component2(repos_root_url, repos_relpath, - scratch_pool); - else - SVN_ERR(svn_wc__db_read_url(&url, db, local_abspath, scratch_pool, - scratch_pool)); + /* Handle special statuses (e.g. added) */ + if (!repos_relpath) + SVN_ERR(svn_wc__db_read_repos_info(NULL, &repos_relpath, + &repos_root_url, NULL, + db, local_abspath, + scratch_pool, scratch_pool)); + + url = svn_path_url_add_component2(repos_root_url, repos_relpath, + scratch_pool); } else { Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c Sun Feb 22 16:52:05 2015 @@ -6129,8 +6129,8 @@ svn_wc__complete_directory_add(svn_wc_co original_repos_relpath, original_root_url, original_uuid, original_revision, NULL /* children */, - FALSE /* is_move */, svn_depth_infinity, + FALSE /* is_move */, NULL /* conflict */, NULL /* work_items */, scratch_pool)); Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/upgrade.c URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/upgrade.c?rev=1661492&r1=1661491&r2=1661492&view=diff ============================================================================== --- subversion/branches/move-tracking-2/subversion/libsvn_wc/upgrade.c (original) +++ subversion/branches/move-tracking-2/subversion/libsvn_wc/upgrade.c Sun Feb 22 16:52:05 2015 @@ -37,6 +37,7 @@ #include "tree_conflicts.h" #include "wc-queries.h" /* for STMT_* */ #include "workqueue.h" +#include "token-map.h" #include "svn_private_config.h" #include "private/svn_wc_private.h" @@ -824,6 +825,190 @@ migrate_tree_conflict_data(svn_sqlite__d return SVN_NO_ERROR; } +/* ### need much more docco + + ### this function should be called within a sqlite transaction. it makes + ### assumptions around this fact. + + Apply the various sets of properties to the database nodes based on + their existence/presence, the current state of the node, and the original + format of the working copy which provided these property sets. +*/ +static svn_error_t * +upgrade_apply_props(svn_sqlite__db_t *sdb, + const char *dir_abspath, + const char *local_relpath, + apr_hash_t *base_props, + apr_hash_t *revert_props, + apr_hash_t *working_props, + int original_format, + apr_int64_t wc_id, + apr_pool_t *scratch_pool) +{ + svn_sqlite__stmt_t *stmt; + svn_boolean_t have_row; + int top_op_depth = -1; + int below_op_depth = -1; + svn_wc__db_status_t top_presence; + svn_wc__db_status_t below_presence; + int affected_rows; + + /* ### working_props: use set_props_txn. + ### if working_props == NULL, then skip. what if they equal the + ### pristine props? we should probably do the compare here. + ### + ### base props go into WORKING_NODE if avail, otherwise BASE. + ### + ### revert only goes into BASE. (and WORKING better be there!) + + Prior to 1.4.0 (ORIGINAL_FORMAT < 8), REVERT_PROPS did not exist. If a + file was deleted, then a copy (potentially with props) was disallowed + and could not replace the deletion. An addition *could* be performed, + but that would never bring its own props. + + 1.4.0 through 1.4.5 created the concept of REVERT_PROPS, but had a + bug in svn_wc_add_repos_file2() whereby a copy-with-props did NOT + construct a REVERT_PROPS if the target had no props. Thus, reverting + the delete/copy would see no REVERT_PROPS to restore, leaving the + props from the copy source intact, and appearing as if they are (now) + the base props for the previously-deleted file. (wc corruption) + + 1.4.6 ensured that an empty REVERT_PROPS would be established at all + times. See issue 2530, and r861670 as starting points. + + We will use ORIGINAL_FORMAT and SVN_WC__NO_REVERT_FILES to determine + the handling of our inputs, relative to the state of this node. + */ + + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_NODE_INFO)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + if (have_row) + { + top_op_depth = svn_sqlite__column_int(stmt, 0); + top_presence = svn_sqlite__column_token(stmt, 3, presence_map); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + if (have_row) + { + below_presence = svn_sqlite__column_token(stmt, 3, presence_map); + + /* There might be an intermediate layer on mixed-revision copies, + or when BASE is shadowed */ + if (below_presence == svn_wc__db_status_not_present + || below_presence == svn_wc__db_status_deleted) + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + if (have_row) + { + below_presence = svn_sqlite__column_token(stmt, 3, presence_map); + below_op_depth = svn_sqlite__column_int(stmt, 0); + } + } + } + SVN_ERR(svn_sqlite__reset(stmt)); + + /* Detect the buggy scenario described above. We cannot upgrade this + working copy if we have no idea where BASE_PROPS should go. */ + if (original_format > SVN_WC__NO_REVERT_FILES + && revert_props == NULL + && top_op_depth != -1 + && top_presence == svn_wc__db_status_normal + && below_op_depth != -1 + && below_presence != svn_wc__db_status_not_present) + { + /* There should be REVERT_PROPS, so it appears that we just ran into + the described bug. Sigh. */ + return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL, + _("The properties of '%s' are in an " + "indeterminate state and cannot be " + "upgraded. See issue #2530."), + svn_dirent_local_style( + svn_dirent_join(dir_abspath, local_relpath, + scratch_pool), scratch_pool)); + } + + /* Need at least one row, or two rows if there are revert props */ + if (top_op_depth == -1 + || (below_op_depth == -1 && revert_props)) + return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL, + _("Insufficient NODES rows for '%s'"), + svn_dirent_local_style( + svn_dirent_join(dir_abspath, local_relpath, + scratch_pool), scratch_pool)); + + /* one row, base props only: upper row gets base props + two rows, base props only: lower row gets base props + two rows, revert props only: lower row gets revert props + two rows, base and revert props: upper row gets base, lower gets revert */ + + + if (revert_props || below_op_depth == -1) + { + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPDATE_NODE_PROPS)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", + wc_id, local_relpath, top_op_depth)); + SVN_ERR(svn_sqlite__bind_properties(stmt, 4, base_props, scratch_pool)); + SVN_ERR(svn_sqlite__update(&affected_rows, stmt)); + + SVN_ERR_ASSERT(affected_rows == 1); + } + + if (below_op_depth != -1) + { + apr_hash_t *props = revert_props ? revert_props : base_props; + + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPDATE_NODE_PROPS)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", + wc_id, local_relpath, below_op_depth)); + SVN_ERR(svn_sqlite__bind_properties(stmt, 4, props, scratch_pool)); + SVN_ERR(svn_sqlite__update(&affected_rows, stmt)); + + SVN_ERR_ASSERT(affected_rows == 1); + } + + /* If there are WORKING_PROPS, then they always go into ACTUAL_NODE. */ + if (working_props != NULL + && base_props != NULL) + { + apr_array_header_t *diffs; + + SVN_ERR(svn_prop_diffs(&diffs, working_props, base_props, scratch_pool)); + + if (diffs->nelts == 0) + working_props = NULL; /* No differences */ + } + + if (working_props != NULL) + { + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPDATE_ACTUAL_PROPS)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath)); + SVN_ERR(svn_sqlite__bind_properties(stmt, 3, working_props, + scratch_pool)); + SVN_ERR(svn_sqlite__update(&affected_rows, stmt)); + + if (affected_rows == 0) + { + /* We have to insert a row in ACTUAL */ + + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_INSERT_ACTUAL_PROPS)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath)); + if (*local_relpath != '\0') + SVN_ERR(svn_sqlite__bind_text(stmt, 3, + svn_relpath_dirname(local_relpath, + scratch_pool))); + SVN_ERR(svn_sqlite__bind_properties(stmt, 4, working_props, + scratch_pool)); + return svn_error_trace(svn_sqlite__step_done(stmt)); + } + } + + return SVN_NO_ERROR; +} + struct bump_baton { const char *wcroot_abspath; @@ -899,7 +1084,7 @@ migrate_node_props(const char *dir_abspa SVN_ERR(read_propfile(&working_props, working_abspath, scratch_pool, scratch_pool)); - return svn_error_trace(svn_wc__db_upgrade_apply_props( + return svn_error_trace(upgrade_apply_props( sdb, new_wcroot_abspath, svn_relpath_join(dir_relpath, name, scratch_pool), base_props, revert_props, working_props, @@ -1671,6 +1856,43 @@ bump_to_31(void *baton, return SVN_NO_ERROR; } +static svn_error_t * +upgrade_apply_dav_cache(svn_sqlite__db_t *sdb, + const char *dir_relpath, + apr_int64_t wc_id, + apr_hash_t *cache_values, + apr_pool_t *scratch_pool) +{ + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_hash_index_t *hi; + svn_sqlite__stmt_t *stmt; + + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPDATE_BASE_NODE_DAV_CACHE)); + + /* Iterate over all the wcprops, writing each one to the wc_db. */ + for (hi = apr_hash_first(scratch_pool, cache_values); + hi; + hi = apr_hash_next(hi)) + { + const char *name = apr_hash_this_key(hi); + apr_hash_t *props = apr_hash_this_val(hi); + const char *local_relpath; + + svn_pool_clear(iterpool); + + local_relpath = svn_relpath_join(dir_relpath, name, iterpool); + + SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath)); + SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, iterpool)); + SVN_ERR(svn_sqlite__step_done(stmt)); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + struct upgrade_data_t { svn_sqlite__db_t *sdb; @@ -1808,8 +2030,8 @@ upgrade_to_wcng(void **dir_baton, SVN_ERR(read_wcprops(&all_wcprops, dir_abspath, scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_upgrade_apply_dav_cache(data->sdb, dir_relpath, - all_wcprops, scratch_pool)); + SVN_ERR(upgrade_apply_dav_cache(data->sdb, dir_relpath, wc_id, + all_wcprops, scratch_pool)); } /* Upgrade all the properties (including "this dir").
