diff options
Diffstat (limited to 'subversion/libsvn_wc/upgrade.c')
-rw-r--r-- | subversion/libsvn_wc/upgrade.c | 499 |
1 files changed, 448 insertions, 51 deletions
diff --git a/subversion/libsvn_wc/upgrade.c b/subversion/libsvn_wc/upgrade.c index afb029c..af615fd 100644 --- a/subversion/libsvn_wc/upgrade.c +++ b/subversion/libsvn_wc/upgrade.c @@ -31,6 +31,7 @@ #include "wc.h" #include "adm_files.h" +#include "conflicts.h" #include "entries.h" #include "wc_db.h" #include "tree_conflicts.h" @@ -150,7 +151,7 @@ read_one_proplist(apr_hash_t *all_wcprops, proplist = apr_hash_make(result_pool); SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, result_pool)); - apr_hash_set(all_wcprops, name, APR_HASH_KEY_STRING, proplist); + svn_hash_sets(all_wcprops, name, proplist); return SVN_NO_ERROR; } @@ -179,8 +180,7 @@ read_many_wcprops(apr_hash_t **all_wcprops, scratch_pool); SVN_ERR(read_propfile(&wcprops, propfile_abspath, result_pool, iterpool)); if (wcprops != NULL) - apr_hash_set(*all_wcprops, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING, - wcprops); + svn_hash_sets(*all_wcprops, SVN_WC_ENTRY_THIS_DIR, wcprops); props_dir_abspath = svn_wc__adm_child(dir_abspath, WCPROPS_SUBDIR_FOR_FILES, scratch_pool); @@ -202,9 +202,7 @@ read_many_wcprops(apr_hash_t **all_wcprops, SVN_ERR(read_propfile(&wcprops, propfile_abspath, result_pool, iterpool)); SVN_ERR_ASSERT(wcprops != NULL); - apr_hash_set(*all_wcprops, - apr_pstrdup(result_pool, name), APR_HASH_KEY_STRING, - wcprops); + svn_hash_sets(*all_wcprops, apr_pstrdup(result_pool, name), wcprops); } svn_pool_destroy(iterpool); @@ -614,8 +612,7 @@ ensure_repos_info(svn_wc_entry_t *entry, for (hi = apr_hash_first(scratch_pool, repos_cache); hi; hi = apr_hash_next(hi)) { - if (svn_uri__is_child(svn__apr_hash_index_key(hi), entry->url, - scratch_pool)) + if (svn_uri__is_ancestor(svn__apr_hash_index_key(hi), entry->url)) { if (!entry->repos) entry->repos = svn__apr_hash_index_key(hi); @@ -701,9 +698,9 @@ read_tree_conflicts(apr_hash_t **conflicts, SVN_ERR(svn_wc__deserialize_conflict(&conflict, skel, dir_path, pool, iterpool)); if (conflict != NULL) - apr_hash_set(*conflicts, svn_dirent_basename(conflict->local_abspath, - pool), - APR_HASH_KEY_STRING, conflict); + svn_hash_sets(*conflicts, + svn_dirent_basename(conflict->local_abspath, pool), + conflict); } svn_pool_destroy(iterpool); @@ -793,7 +790,7 @@ migrate_tree_conflict_data(svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) all of them into the new schema. */ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_SELECT_OLD_TREE_CONFLICT)); + STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT)); /* Get all the existing tree conflict data. */ SVN_ERR(svn_sqlite__step(&have_row, stmt)); @@ -820,7 +817,8 @@ migrate_tree_conflict_data(svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) SVN_ERR(svn_sqlite__reset(stmt)); /* Erase all the old tree conflict data. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_ERASE_OLD_CONFLICTS)); + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPGRADE_21_ERASE_OLD_CONFLICTS)); SVN_ERR(svn_sqlite__step_done(stmt)); svn_pool_destroy(iterpool); @@ -1120,16 +1118,14 @@ migrate_text_bases(apr_hash_t **text_bases_info, /* Create a new info struct for this versioned file, or fill in the * existing one if this is the second text-base we've found for it. */ - info = apr_hash_get(*text_bases_info, versioned_file_name, - APR_HASH_KEY_STRING); + info = svn_hash_gets(*text_bases_info, versioned_file_name); if (info == NULL) info = apr_pcalloc(result_pool, sizeof (*info)); file_info = (is_revert_base ? &info->revert_base : &info->normal_base); file_info->sha1_checksum = svn_checksum_dup(sha1_checksum, result_pool); file_info->md5_checksum = svn_checksum_dup(md5_checksum, result_pool); - apr_hash_set(*text_bases_info, versioned_file_name, APR_HASH_KEY_STRING, - info); + svn_hash_sets(*text_bases_info, versioned_file_name, info); } } @@ -1168,7 +1164,8 @@ bump_to_23(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_HAS_WORKING_NODES)); + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPGRADE_23_HAS_WORKING_NODES)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); SVN_ERR(svn_sqlite__reset(stmt)); if (have_row) @@ -1212,7 +1209,7 @@ bump_to_27(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) svn_boolean_t have_row; SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_HAS_ACTUAL_NODES_CONFLICTS)); + STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); SVN_ERR(svn_sqlite__reset(stmt)); if (have_row) @@ -1364,6 +1361,316 @@ bump_to_29(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) return SVN_NO_ERROR; } +svn_error_t * +svn_wc__upgrade_conflict_skel_from_raw(svn_skel_t **conflicts, + svn_wc__db_t *db, + const char *wri_abspath, + const char *local_relpath, + const char *conflict_old, + const char *conflict_wrk, + const char *conflict_new, + const char *prej_file, + const char *tree_conflict_data, + apr_size_t tree_conflict_len, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_skel_t *conflict_data = NULL; + const char *wcroot_abspath; + + SVN_ERR(svn_wc__db_get_wcroot(&wcroot_abspath, db, wri_abspath, + scratch_pool, scratch_pool)); + + if (conflict_old || conflict_new || conflict_wrk) + { + const char *old_abspath = NULL; + const char *new_abspath = NULL; + const char *wrk_abspath = NULL; + + conflict_data = svn_wc__conflict_skel_create(result_pool); + + if (conflict_old) + old_abspath = svn_dirent_join(wcroot_abspath, conflict_old, + scratch_pool); + + if (conflict_new) + new_abspath = svn_dirent_join(wcroot_abspath, conflict_new, + scratch_pool); + + if (conflict_wrk) + wrk_abspath = svn_dirent_join(wcroot_abspath, conflict_wrk, + scratch_pool); + + SVN_ERR(svn_wc__conflict_skel_add_text_conflict(conflict_data, + db, wri_abspath, + wrk_abspath, + old_abspath, + new_abspath, + scratch_pool, + scratch_pool)); + } + + if (prej_file) + { + const char *prej_abspath; + + if (!conflict_data) + conflict_data = svn_wc__conflict_skel_create(result_pool); + + prej_abspath = svn_dirent_join(wcroot_abspath, prej_file, scratch_pool); + + SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_data, + db, wri_abspath, + prej_abspath, + NULL, NULL, NULL, + apr_hash_make(scratch_pool), + scratch_pool, + scratch_pool)); + } + + if (tree_conflict_data) + { + svn_skel_t *tc_skel; + const svn_wc_conflict_description2_t *tc; + const char *local_abspath; + + if (!conflict_data) + conflict_data = svn_wc__conflict_skel_create(scratch_pool); + + tc_skel = svn_skel__parse(tree_conflict_data, tree_conflict_len, + scratch_pool); + + local_abspath = svn_dirent_join(wcroot_abspath, local_relpath, + scratch_pool); + + SVN_ERR(svn_wc__deserialize_conflict(&tc, tc_skel, + svn_dirent_dirname(local_abspath, + scratch_pool), + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(conflict_data, + db, wri_abspath, + tc->reason, + tc->action, + NULL, + scratch_pool, + scratch_pool)); + + switch (tc->operation) + { + case svn_wc_operation_update: + default: + SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_data, + tc->src_left_version, + tc->src_right_version, + scratch_pool, + scratch_pool)); + break; + case svn_wc_operation_switch: + SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict_data, + tc->src_left_version, + tc->src_right_version, + scratch_pool, + scratch_pool)); + break; + case svn_wc_operation_merge: + SVN_ERR(svn_wc__conflict_skel_set_op_merge(conflict_data, + tc->src_left_version, + tc->src_right_version, + scratch_pool, + scratch_pool)); + break; + } + } + else if (conflict_data) + { + SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_data, NULL, NULL, + scratch_pool, + scratch_pool)); + } + + *conflicts = conflict_data; + return SVN_NO_ERROR; +} + +/* Helper function to upgrade a single conflict from bump_to_30 */ +static svn_error_t * +bump_30_upgrade_one_conflict(svn_wc__db_t *wc_db, + const char *wcroot_abspath, + svn_sqlite__stmt_t *stmt, + svn_sqlite__db_t *sdb, + apr_pool_t *scratch_pool) +{ + svn_sqlite__stmt_t *stmt_store; + svn_stringbuf_t *skel_data; + svn_skel_t *conflict_data; + apr_int64_t wc_id = svn_sqlite__column_int64(stmt, 0); + const char *local_relpath = svn_sqlite__column_text(stmt, 1, NULL); + const char *conflict_old = svn_sqlite__column_text(stmt, 2, NULL); + const char *conflict_wrk = svn_sqlite__column_text(stmt, 3, NULL); + const char *conflict_new = svn_sqlite__column_text(stmt, 4, NULL); + const char *prop_reject = svn_sqlite__column_text(stmt, 5, NULL); + apr_size_t tree_conflict_size; + const char *tree_conflict_data = svn_sqlite__column_blob(stmt, 6, + &tree_conflict_size, NULL); + + SVN_ERR(svn_wc__upgrade_conflict_skel_from_raw(&conflict_data, + wc_db, wcroot_abspath, + local_relpath, + conflict_old, + conflict_wrk, + conflict_new, + prop_reject, + tree_conflict_data, + tree_conflict_size, + scratch_pool, scratch_pool)); + + SVN_ERR_ASSERT(conflict_data != NULL); + + skel_data = svn_skel__unparse(conflict_data, scratch_pool); + + SVN_ERR(svn_sqlite__get_statement(&stmt_store, sdb, + STMT_UPGRADE_30_SET_CONFLICT)); + SVN_ERR(svn_sqlite__bindf(stmt_store, "isb", wc_id, local_relpath, + skel_data->data, skel_data->len)); + SVN_ERR(svn_sqlite__step_done(stmt_store)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +bump_to_30(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) +{ + struct bump_baton *bb = baton; + svn_boolean_t have_row; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + svn_sqlite__stmt_t *stmt; + svn_wc__db_t *db; /* Read only temp db */ + + SVN_ERR(svn_wc__db_open(&db, NULL, TRUE /* open_without_upgrade */, FALSE, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + while (have_row) + { + svn_error_t *err; + svn_pool_clear(iterpool); + + err = bump_30_upgrade_one_conflict(db, bb->wcroot_abspath, stmt, sdb, + iterpool); + + if (err) + { + return svn_error_trace( + svn_error_compose_create( + err, + svn_sqlite__reset(stmt))); + } + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + SVN_ERR(svn_sqlite__reset(stmt)); + + SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_30)); + SVN_ERR(svn_wc__db_close(db)); + return SVN_NO_ERROR; +} + +static svn_error_t * +bump_to_31(void *baton, + svn_sqlite__db_t *sdb, + apr_pool_t *scratch_pool) +{ + svn_sqlite__stmt_t *stmt, *stmt_mark_switch_roots; + svn_boolean_t have_row; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_array_header_t *empty_iprops = apr_array_make( + scratch_pool, 0, sizeof(svn_prop_inherited_item_t *)); + svn_boolean_t iprops_column_exists = FALSE; + svn_error_t *err; + + /* Add the inherited_props column to NODES if it does not yet exist. + * + * When using a format >= 31 client to upgrade from old formats which + * did not yet have a NODES table, the inherited_props column has + * already been created as part of the NODES table. Attemping to add + * the inherited_props column will raise an error in this case, so check + * if the column exists first. + * + * Checking for the existence of a column before ALTER TABLE is not + * possible within SQLite. We need to run a separate query and evaluate + * its result in C first. + */ + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_PRAGMA_TABLE_INFO_NODES)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + while (have_row) + { + const char *column_name = svn_sqlite__column_text(stmt, 1, NULL); + + if (strcmp(column_name, "inherited_props") == 0) + { + iprops_column_exists = TRUE; + break; + } + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + SVN_ERR(svn_sqlite__reset(stmt)); + if (!iprops_column_exists) + SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31_ALTER_TABLE)); + + /* Run additional statements to finalize the upgrade to format 31. */ + SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31_FINALIZE)); + + /* Set inherited_props to an empty array for the roots of all + switched subtrees in the WC. This allows subsequent updates + to recognize these roots as needing an iprops cache. */ + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, + STMT_UPGRADE_31_SELECT_WCROOT_NODES)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + err = svn_sqlite__get_statement(&stmt_mark_switch_roots, sdb, + STMT_UPDATE_IPROP); + if (err) + return svn_error_compose_create(err, svn_sqlite__reset(stmt)); + + while (have_row) + { + const char *switched_relpath = svn_sqlite__column_text(stmt, 1, NULL); + apr_int64_t wc_id = svn_sqlite__column_int64(stmt, 0); + + err = svn_sqlite__bindf(stmt_mark_switch_roots, "is", wc_id, + switched_relpath); + if (!err) + err = svn_sqlite__bind_iprops(stmt_mark_switch_roots, 3, + empty_iprops, iterpool); + if (!err) + err = svn_sqlite__step_done(stmt_mark_switch_roots); + if (!err) + err = svn_sqlite__step(&have_row, stmt); + + if (err) + return svn_error_compose_create( + err, + svn_error_compose_create( + /* Reset in either order is OK. */ + svn_sqlite__reset(stmt), + svn_sqlite__reset(stmt_mark_switch_roots))); + } + + err = svn_sqlite__reset(stmt_mark_switch_roots); + if (err) + return svn_error_compose_create(err, svn_sqlite__reset(stmt)); + SVN_ERR(svn_sqlite__reset(stmt)); + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + struct upgrade_data_t { svn_sqlite__db_t *sdb; @@ -1449,21 +1756,20 @@ upgrade_to_wcng(void **dir_baton, SVN_ERR(svn_wc__read_entries_old(&entries, dir_abspath, scratch_pool, scratch_pool)); - this_dir = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING); + this_dir = svn_hash_gets(entries, SVN_WC_ENTRY_THIS_DIR); SVN_ERR(ensure_repos_info(this_dir, dir_abspath, repos_info_func, repos_info_baton, repos_cache, scratch_pool, scratch_pool)); /* Cache repos UUID pairs for when a subdir doesn't have this information */ - if (!apr_hash_get(repos_cache, this_dir->repos, APR_HASH_KEY_STRING)) + if (!svn_hash_gets(repos_cache, this_dir->repos)) { apr_pool_t *hash_pool = apr_hash_pool_get(repos_cache); - apr_hash_set(repos_cache, - apr_pstrdup(hash_pool, this_dir->repos), - APR_HASH_KEY_STRING, - apr_pstrdup(hash_pool, this_dir->uuid)); + svn_hash_sets(repos_cache, + apr_pstrdup(hash_pool, this_dir->repos), + apr_pstrdup(hash_pool, this_dir->uuid)); } old_wcroot_abspath = svn_dirent_get_longest_ancestor(dir_abspath, @@ -1517,16 +1823,8 @@ upgrade_to_wcng(void **dir_baton, return SVN_NO_ERROR; } - -/* Return a string indicating the released version (or versions) of - * Subversion that used WC format number WC_FORMAT, or some other - * suitable string if no released version used WC_FORMAT. - * - * ### It's not ideal to encode this sort of knowledge in this low-level - * library. On the other hand, it doesn't need to be updated often and - * should be easily found when it does need to be updated. */ -static const char * -version_string_from_format(int wc_format) +const char * +svn_wc__version_string_from_format(int wc_format) { switch (wc_format) { @@ -1534,6 +1832,7 @@ version_string_from_format(int wc_format) case 8: return "1.4"; case 9: return "1.5"; case 10: return "1.6"; + case SVN_WC__WC_NG_VERSION: return "1.7"; } return _("(unreleased development version)"); } @@ -1546,6 +1845,7 @@ svn_wc__upgrade_sdb(int *result_format, apr_pool_t *scratch_pool) { struct bump_baton bb; + bb.wcroot_abspath = wcroot_abspath; if (start_format < SVN_WC__WC_NG_VERSION /* 12 */) @@ -1555,7 +1855,7 @@ svn_wc__upgrade_sdb(int *result_format, svn_dirent_local_style(wcroot_abspath, scratch_pool), start_format, - version_string_from_format(start_format)); + svn_wc__version_string_from_format(start_format)); /* Early WCNG formats no longer supported. */ if (start_format < 19) @@ -1636,6 +1936,16 @@ svn_wc__upgrade_sdb(int *result_format, *result_format = 29; /* FALLTHROUGH */ + case 29: + SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_30, &bb, + scratch_pool)); + *result_format = 30; + + case 30: + SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_31, &bb, + scratch_pool)); + *result_format = 31; + /* FALLTHROUGH */ /* ### future bumps go here. */ #if 0 case XXX-1: @@ -1645,6 +1955,13 @@ svn_wc__upgrade_sdb(int *result_format, *result_format = XXX; /* FALLTHROUGH */ #endif + case SVN_WC__VERSION: + /* already upgraded */ + *result_format = SVN_WC__VERSION; + + SVN_SQLITE__WITH_LOCK( + svn_wc__db_install_schema_statistics(sdb, scratch_pool), + sdb); } #ifdef SVN_DEBUG @@ -1772,7 +2089,7 @@ is_old_wcroot(const char *local_abspath, { return svn_error_createf( SVN_ERR_WC_INVALID_OP_ON_CWD, err, - _("Can't upgrade '%s' as it is not a pre-1.7 working copy directory"), + _("Can't upgrade '%s' as it is not a working copy"), svn_dirent_local_style(local_abspath, scratch_pool)); } else if (svn_dirent_is_root(local_abspath, strlen(local_abspath))) @@ -1788,7 +2105,7 @@ is_old_wcroot(const char *local_abspath, return SVN_NO_ERROR; } - entry = apr_hash_get(entries, name, APR_HASH_KEY_STRING); + entry = svn_hash_gets(entries, name); if (!entry || entry->absent || (entry->deleted && entry->schedule != svn_wc_schedule_add) @@ -1808,7 +2125,7 @@ is_old_wcroot(const char *local_abspath, parent_abspath = svn_dirent_join(parent_abspath, name, scratch_pool); break; } - entry = apr_hash_get(entries, name, APR_HASH_KEY_STRING); + entry = svn_hash_gets(entries, name); if (!entry || entry->absent || (entry->deleted && entry->schedule != svn_wc_schedule_add) @@ -1821,7 +2138,7 @@ is_old_wcroot(const char *local_abspath, return svn_error_createf( SVN_ERR_WC_INVALID_OP_ON_CWD, NULL, - _("Can't upgrade '%s' as it is not a pre-1.7 working copy root," + _("Can't upgrade '%s' as it is not a working copy root," " the root is '%s'"), svn_dirent_local_style(local_abspath, scratch_pool), svn_dirent_local_style(parent_abspath, scratch_pool)); @@ -1881,6 +2198,51 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx, apr_hash_t *entries; const char *root_adm_abspath; upgrade_working_copy_baton_t cb_baton; + svn_error_t *err; + int result_format; + svn_boolean_t bumped_format; + + /* Try upgrading a wc-ng-style working copy. */ + SVN_ERR(svn_wc__db_open(&db, NULL /* ### config */, TRUE, FALSE, + scratch_pool, scratch_pool)); + + + err = svn_wc__db_bump_format(&result_format, &bumped_format, + db, local_abspath, + scratch_pool); + if (err) + { + if (err->apr_err != SVN_ERR_WC_UPGRADE_REQUIRED) + { + return svn_error_trace( + svn_error_compose_create( + err, + svn_wc__db_close(db))); + } + + svn_error_clear(err); + /* Pre 1.7: Fall through */ + } + else + { + /* Auto-upgrade worked! */ + SVN_ERR(svn_wc__db_close(db)); + + SVN_ERR_ASSERT(result_format == SVN_WC__VERSION); + + if (bumped_format && notify_func) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_upgraded_path, + scratch_pool); + + notify_func(notify_baton, notify, scratch_pool); + } + + return SVN_NO_ERROR; + } SVN_ERR(is_old_wcroot(local_abspath, scratch_pool)); @@ -1893,25 +2255,19 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx, 'cleanup' with a new client will complete any outstanding upgrade. */ - SVN_ERR(svn_wc__db_open(&db, - NULL /* ### config */, FALSE, FALSE, - scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__read_entries_old(&entries, local_abspath, scratch_pool, scratch_pool)); - this_dir = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, - APR_HASH_KEY_STRING); + this_dir = svn_hash_gets(entries, SVN_WC_ENTRY_THIS_DIR); SVN_ERR(ensure_repos_info(this_dir, local_abspath, repos_info_func, repos_info_baton, repos_cache, scratch_pool, scratch_pool)); /* Cache repos UUID pairs for when a subdir doesn't have this information */ - if (!apr_hash_get(repos_cache, this_dir->repos, APR_HASH_KEY_STRING)) - apr_hash_set(repos_cache, - apr_pstrdup(scratch_pool, this_dir->repos), - APR_HASH_KEY_STRING, - apr_pstrdup(scratch_pool, this_dir->uuid)); + if (!svn_hash_gets(repos_cache, this_dir->repos)) + svn_hash_sets(repos_cache, + apr_pstrdup(scratch_pool, this_dir->repos), + apr_pstrdup(scratch_pool, this_dir->uuid)); /* Create the new DB in the temporary root wc/.svn/tmp/wcng/.svn */ data.root_abspath = svn_dirent_join(svn_wc__adm_child(local_abspath, "tmp", @@ -1994,3 +2350,44 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx, return SVN_NO_ERROR; } +svn_error_t * +svn_wc__upgrade_add_external_info(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_node_kind_t kind, + const char *def_local_abspath, + const char *repos_relpath, + const char *repos_root_url, + const char *repos_uuid, + svn_revnum_t def_peg_revision, + svn_revnum_t def_revision, + apr_pool_t *scratch_pool) +{ + svn_node_kind_t db_kind; + switch (kind) + { + case svn_node_dir: + db_kind = svn_node_dir; + break; + + case svn_node_file: + db_kind = svn_node_file; + break; + + case svn_node_unknown: + db_kind = svn_node_unknown; + break; + + default: + SVN_ERR_MALFUNCTION(); + } + + SVN_ERR(svn_wc__db_upgrade_insert_external(wc_ctx->db, local_abspath, + db_kind, + svn_dirent_dirname(local_abspath, + scratch_pool), + def_local_abspath, repos_relpath, + repos_root_url, repos_uuid, + def_peg_revision, def_revision, + scratch_pool)); + return SVN_NO_ERROR; +} |