diff options
Diffstat (limited to 'subversion/libsvn_wc/entries.c')
-rw-r--r-- | subversion/libsvn_wc/entries.c | 422 |
1 files changed, 269 insertions, 153 deletions
diff --git a/subversion/libsvn_wc/entries.c b/subversion/libsvn_wc/entries.c index c4517b0..24dae50 100644 --- a/subversion/libsvn_wc/entries.c +++ b/subversion/libsvn_wc/entries.c @@ -34,9 +34,11 @@ #include "svn_path.h" #include "svn_ctype.h" #include "svn_string.h" +#include "svn_hash.h" #include "wc.h" #include "adm_files.h" +#include "conflicts.h" #include "entries.h" #include "lock.h" #include "tree_conflicts.h" @@ -55,22 +57,23 @@ typedef struct db_node_t { apr_int64_t wc_id; const char *local_relpath; - apr_int64_t op_depth; + int op_depth; apr_int64_t repos_id; const char *repos_relpath; const char *parent_relpath; svn_wc__db_status_t presence; svn_revnum_t revision; - svn_node_kind_t kind; /* ### should switch to svn_wc__db_kind_t */ + svn_node_kind_t kind; svn_checksum_t *checksum; - svn_filesize_t translated_size; + svn_filesize_t recorded_size; svn_revnum_t changed_rev; apr_time_t changed_date; const char *changed_author; svn_depth_t depth; - apr_time_t last_mod_time; + apr_time_t recorded_time; apr_hash_t *properties; svn_boolean_t file_external; + apr_array_header_t *inherited_props; } db_node_t; typedef struct db_actual_node_t { @@ -148,7 +151,7 @@ check_file_external(svn_wc_entry_t *entry, apr_pool_t *scratch_pool) { svn_wc__db_status_t status; - svn_wc__db_kind_t kind; + svn_node_kind_t kind; const char *repos_relpath; svn_revnum_t peg_revision; svn_revnum_t revision; @@ -169,7 +172,7 @@ check_file_external(svn_wc_entry_t *entry, } if (status == svn_wc__db_status_normal - && kind == svn_wc__db_kind_file) + && kind == svn_node_file) { entry->file_external_path = repos_relpath; if (SVN_IS_VALID_REVNUM(peg_revision)) @@ -204,9 +207,10 @@ check_file_external(svn_wc_entry_t *entry, */ static svn_error_t * get_info_for_deleted(svn_wc_entry_t *entry, - svn_wc__db_kind_t *kind, + svn_node_kind_t *kind, const char **repos_relpath, const svn_checksum_t **checksum, + svn_wc__db_lock_t **lock, svn_wc__db_t *db, const char *entry_abspath, const svn_wc_entry_t *parent_entry, @@ -229,22 +233,13 @@ get_info_for_deleted(svn_wc_entry_t *entry, &entry->depth, checksum, NULL, - NULL /* lock */, - &entry->has_props, + lock, + &entry->has_props, NULL, NULL, db, entry_abspath, result_pool, scratch_pool)); - - if (*repos_relpath == NULL) - SVN_ERR(svn_wc__db_scan_base_repos(repos_relpath, - &entry->repos, - &entry->uuid, - db, - entry_abspath, - result_pool, - scratch_pool)); } else { @@ -263,7 +258,7 @@ get_info_for_deleted(svn_wc_entry_t *entry, &entry->depth, checksum, NULL, - &entry->has_props, + &entry->has_props, NULL, db, entry_abspath, result_pool, @@ -272,7 +267,7 @@ get_info_for_deleted(svn_wc_entry_t *entry, SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, - &work_del_abspath, + &work_del_abspath, NULL, db, entry_abspath, scratch_pool, scratch_pool)); @@ -304,7 +299,8 @@ get_info_for_deleted(svn_wc_entry_t *entry, svn_wc__db_status_t status; SVN_ERR(svn_wc__db_base_get_info(&status, NULL, &entry->revision, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, lock, NULL, NULL, + NULL, db, entry_abspath, result_pool, scratch_pool)); @@ -384,7 +380,7 @@ read_one_entry(const svn_wc_entry_t **new_entry, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_wc__db_kind_t kind; + svn_node_kind_t kind; svn_wc__db_status_t status; svn_wc__db_lock_t *lock; const char *repos_relpath; @@ -461,9 +457,10 @@ read_one_entry(const svn_wc_entry_t **new_entry, child_abspath = svn_dirent_join(dir_abspath, child_name, scratch_pool); - SVN_ERR(svn_wc__db_read_conflicts(&child_conflicts, - db, child_abspath, - scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__read_conflicts(&child_conflicts, + db, child_abspath, + FALSE /* create tempfiles */, + scratch_pool, scratch_pool)); for (j = 0; j < child_conflicts->nelts; j++) { @@ -475,8 +472,7 @@ read_one_entry(const svn_wc_entry_t **new_entry, { if (!tree_conflicts) tree_conflicts = apr_hash_make(scratch_pool); - apr_hash_set(tree_conflicts, child_name, - APR_HASH_KEY_STRING, conflict); + svn_hash_sets(tree_conflicts, child_name, conflict); } } } @@ -525,7 +521,7 @@ read_one_entry(const svn_wc_entry_t **new_entry, { const char *work_del_abspath; SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL, - &work_del_abspath, + &work_del_abspath, NULL, db, entry_abspath, scratch_pool, scratch_pool)); @@ -572,7 +568,7 @@ read_one_entry(const svn_wc_entry_t **new_entry, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, db, entry_abspath, scratch_pool, scratch_pool)); @@ -637,7 +633,10 @@ read_one_entry(const svn_wc_entry_t **new_entry, /* ### scan_addition may need to be updated to avoid returning ### status_copied in this case. */ } - else if (work_status == svn_wc__db_status_copied) + /* For backwards-compatiblity purposes we treat moves just like + * regular copies. */ + else if (work_status == svn_wc__db_status_copied || + work_status == svn_wc__db_status_moved_here) { entry->copied = TRUE; @@ -662,7 +661,8 @@ read_one_entry(const svn_wc_entry_t **new_entry, svn_boolean_t is_copied_child; svn_boolean_t is_mixed_rev = FALSE; - SVN_ERR_ASSERT(work_status == svn_wc__db_status_copied); + SVN_ERR_ASSERT(work_status == svn_wc__db_status_copied || + work_status == svn_wc__db_status_moved_here); /* If this node inherits copyfrom information from an ancestor node, then it must be a copied child. */ @@ -713,8 +713,7 @@ read_one_entry(const svn_wc_entry_t **new_entry, &parent_repos_relpath, &parent_root_url, NULL, NULL, - db, - parent_abspath, + db, parent_abspath, scratch_pool, scratch_pool); if (err) @@ -826,6 +825,7 @@ read_one_entry(const svn_wc_entry_t **new_entry, &kind, &repos_relpath, &checksum, + &lock, db, entry_abspath, parent_entry, have_base, have_more_work, @@ -836,11 +836,11 @@ read_one_entry(const svn_wc_entry_t **new_entry, if (entry->depth == svn_depth_unknown) entry->depth = svn_depth_infinity; - if (kind == svn_wc__db_kind_dir) + if (kind == svn_node_dir) entry->kind = svn_node_dir; - else if (kind == svn_wc__db_kind_file) + else if (kind == svn_node_file) entry->kind = svn_node_file; - else if (kind == svn_wc__db_kind_symlink) + else if (kind == svn_node_symlink) entry->kind = svn_node_file; /* ### no symlink kind */ else entry->kind = svn_node_unknown; @@ -878,37 +878,53 @@ read_one_entry(const svn_wc_entry_t **new_entry, if (conflicted) { - const apr_array_header_t *conflicts; - int j; - SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, entry_abspath, - scratch_pool, scratch_pool)); + svn_skel_t *conflict; + svn_boolean_t text_conflicted; + svn_boolean_t prop_conflicted; + SVN_ERR(svn_wc__db_read_conflict(&conflict, db, entry_abspath, + scratch_pool, scratch_pool)); - for (j = 0; j < conflicts->nelts; j++) + SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, &text_conflicted, + &prop_conflicted, NULL, + db, dir_abspath, conflict, + scratch_pool, scratch_pool)); + + if (text_conflicted) { - const svn_wc_conflict_description2_t *cd; - cd = APR_ARRAY_IDX(conflicts, j, - const svn_wc_conflict_description2_t *); + const char *my_abspath; + const char *their_old_abspath; + const char *their_abspath; + SVN_ERR(svn_wc__conflict_read_text_conflict(&my_abspath, + &their_old_abspath, + &their_abspath, + db, dir_abspath, + conflict, scratch_pool, + scratch_pool)); - switch (cd->kind) - { - case svn_wc_conflict_kind_text: - if (cd->base_abspath) - entry->conflict_old = svn_dirent_basename(cd->base_abspath, - result_pool); - if (cd->their_abspath) - entry->conflict_new = svn_dirent_basename(cd->their_abspath, - result_pool); - if (cd->my_abspath) - entry->conflict_wrk = svn_dirent_basename(cd->my_abspath, - result_pool); - break; - case svn_wc_conflict_kind_property: - entry->prejfile = svn_dirent_basename(cd->their_abspath, - result_pool); - break; - case svn_wc_conflict_kind_tree: - break; - } + if (my_abspath) + entry->conflict_wrk = svn_dirent_basename(my_abspath, result_pool); + + if (their_old_abspath) + entry->conflict_old = svn_dirent_basename(their_old_abspath, + result_pool); + + if (their_abspath) + entry->conflict_new = svn_dirent_basename(their_abspath, + result_pool); + } + + if (prop_conflicted) + { + const char *prej_abspath; + + SVN_ERR(svn_wc__conflict_read_prop_conflict(&prej_abspath, NULL, + NULL, NULL, NULL, + db, dir_abspath, + conflict, scratch_pool, + scratch_pool)); + + if (prej_abspath) + entry->prejfile = svn_dirent_basename(prej_abspath, result_pool); } } @@ -922,7 +938,7 @@ read_one_entry(const svn_wc_entry_t **new_entry, /* Let's check for a file external. ugh. */ if (status == svn_wc__db_status_normal - && kind == svn_wc__db_kind_file) + && kind == svn_node_file) SVN_ERR(check_file_external(entry, db, entry_abspath, dir_abspath, result_pool, scratch_pool)); @@ -956,7 +972,7 @@ read_entries_new(apr_hash_t **result_entries, "" /* name */, NULL /* parent_entry */, result_pool, iterpool)); - apr_hash_set(entries, "", APR_HASH_KEY_STRING, parent_entry); + svn_hash_sets(entries, "", parent_entry); /* Use result_pool so that the child names (used by reference, rather than copied) appear in result_pool. */ @@ -973,7 +989,7 @@ read_entries_new(apr_hash_t **result_entries, SVN_ERR(read_one_entry(&entry, db, wc_id, local_abspath, name, parent_entry, result_pool, iterpool)); - apr_hash_set(entries, entry->name, APR_HASH_KEY_STRING, entry); + svn_hash_sets(entries, entry->name, entry); } svn_pool_destroy(iterpool); @@ -1350,7 +1366,7 @@ prune_deleted(apr_hash_t **entries_pruned, SVN_ERR(svn_wc__entry_is_hidden(&hidden, entry)); if (!hidden) - apr_hash_set(*entries_pruned, key, APR_HASH_KEY_STRING, entry); + svn_hash_sets(*entries_pruned, key, entry); } return SVN_NO_ERROR; @@ -1376,10 +1392,10 @@ entries_read_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool) } svn_error_t * -svn_wc_entries_read(apr_hash_t **entries, - svn_wc_adm_access_t *adm_access, - svn_boolean_t show_hidden, - apr_pool_t *pool) +svn_wc__entries_read_internal(apr_hash_t **entries, + svn_wc_adm_access_t *adm_access, + svn_boolean_t show_hidden, + apr_pool_t *pool) { apr_hash_t *new_entries; @@ -1388,7 +1404,7 @@ svn_wc_entries_read(apr_hash_t **entries, { svn_wc__db_t *db = svn_wc__adm_get_db(adm_access); const char *local_abspath = svn_wc__adm_access_abspath(adm_access); - apr_pool_t *result_pool = svn_wc_adm_access_pool(adm_access); + apr_pool_t *result_pool = svn_wc__adm_access_pool_internal(adm_access); svn_sqlite__db_t *sdb; struct entries_read_baton_t erb; @@ -1412,12 +1428,21 @@ svn_wc_entries_read(apr_hash_t **entries, *entries = new_entries; else SVN_ERR(prune_deleted(entries, new_entries, - svn_wc_adm_access_pool(adm_access), + svn_wc__adm_access_pool_internal(adm_access), pool)); return SVN_NO_ERROR; } +svn_error_t * +svn_wc_entries_read(apr_hash_t **entries, + svn_wc_adm_access_t *adm_access, + svn_boolean_t show_hidden, + apr_pool_t *pool) +{ + return svn_error_trace(svn_wc__entries_read_internal(entries, adm_access, + show_hidden, pool)); +} /* No transaction required: called from write_entry which is itself transaction-wrapped. */ @@ -1431,7 +1456,7 @@ insert_node(svn_sqlite__db_t *sdb, 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, "isisnnnnsnrisnnni", + SVN_ERR(svn_sqlite__bindf(stmt, "isdsnnnnsnrisnnni", node->wc_id, node->local_relpath, node->op_depth, @@ -1441,7 +1466,7 @@ insert_node(svn_sqlite__db_t *sdb, node->changed_rev, node->changed_date, node->changed_author, - node->last_mod_time)); + node->recorded_time)); if (node->repos_relpath) { @@ -1449,7 +1474,7 @@ insert_node(svn_sqlite__db_t *sdb, node->repos_id)); SVN_ERR(svn_sqlite__bind_text(stmt, 6, node->repos_relpath)); - SVN_ERR(svn_sqlite__bind_int64(stmt, 7, node->revision)); + SVN_ERR(svn_sqlite__bind_revnum(stmt, 7, node->revision)); } if (node->presence == svn_wc__db_status_normal) @@ -1463,7 +1488,7 @@ insert_node(svn_sqlite__db_t *sdb, 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, "absent")); + SVN_ERR(svn_sqlite__bind_text(stmt, 8, "server-excluded")); if (node->kind == svn_node_none) SVN_ERR(svn_sqlite__bind_text(stmt, 10, "unknown")); @@ -1491,12 +1516,16 @@ insert_node(svn_sqlite__db_t *sdb, SVN_ERR(svn_sqlite__bind_properties(stmt, 15, node->properties, scratch_pool)); - if (node->translated_size != SVN_INVALID_FILESIZE) - SVN_ERR(svn_sqlite__bind_int64(stmt, 16, node->translated_size)); + 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) + SVN_ERR(svn_sqlite__bind_iprops(stmt, 23, node->inherited_props, + scratch_pool)); + SVN_ERR(svn_sqlite__insert(NULL, stmt)); return SVN_NO_ERROR; @@ -1506,10 +1535,13 @@ insert_node(svn_sqlite__db_t *sdb, /* */ static svn_error_t * insert_actual_node(svn_sqlite__db_t *sdb, + svn_wc__db_t *db, + const char *wri_abspath, const db_actual_node_t *actual_node, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; + svn_skel_t *conflict_data = NULL; SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_ACTUAL_NODE)); @@ -1521,24 +1553,57 @@ insert_actual_node(svn_sqlite__db_t *sdb, SVN_ERR(svn_sqlite__bind_properties(stmt, 4, actual_node->properties, scratch_pool)); - if (actual_node->conflict_old) + if (actual_node->changelist) + SVN_ERR(svn_sqlite__bind_text(stmt, 5, actual_node->changelist)); + + SVN_ERR(svn_wc__upgrade_conflict_skel_from_raw( + &conflict_data, + db, wri_abspath, + actual_node->local_relpath, + actual_node->conflict_old, + actual_node->conflict_working, + actual_node->conflict_new, + actual_node->prop_reject, + actual_node->tree_conflict_data, + actual_node->tree_conflict_data + ? strlen(actual_node->tree_conflict_data) + : 0, + scratch_pool, scratch_pool)); + + if (conflict_data) { - SVN_ERR(svn_sqlite__bind_text(stmt, 5, actual_node->conflict_old)); - SVN_ERR(svn_sqlite__bind_text(stmt, 6, actual_node->conflict_new)); - SVN_ERR(svn_sqlite__bind_text(stmt, 7, actual_node->conflict_working)); + svn_stringbuf_t *data = svn_skel__unparse(conflict_data, scratch_pool); + + SVN_ERR(svn_sqlite__bind_blob(stmt, 6, data->data, data->len)); } - if (actual_node->prop_reject) - SVN_ERR(svn_sqlite__bind_text(stmt, 8, actual_node->prop_reject)); + /* Execute and reset the insert clause. */ + return svn_error_trace(svn_sqlite__insert(NULL, stmt)); +} - if (actual_node->changelist) - SVN_ERR(svn_sqlite__bind_text(stmt, 9, actual_node->changelist)); +static svn_boolean_t +is_switched(db_node_t *parent, + db_node_t *child, + apr_pool_t *scratch_pool) +{ + if (parent && child) + { + if (parent->repos_id != child->repos_id) + return TRUE; - if (actual_node->tree_conflict_data) - SVN_ERR(svn_sqlite__bind_text(stmt, 10, actual_node->tree_conflict_data)); + if (parent->repos_relpath && child->repos_relpath) + { + const char *unswitched + = svn_relpath_join(parent->repos_relpath, + svn_relpath_basename(child->local_relpath, + scratch_pool), + scratch_pool); + if (strcmp(unswitched, child->repos_relpath)) + return TRUE; + } + } - /* Execute and reset the insert clause. */ - return svn_error_trace(svn_sqlite__insert(NULL, stmt)); + return FALSE; } struct write_baton { @@ -1548,6 +1613,15 @@ struct write_baton { apr_hash_t *tree_conflicts; }; +#define WRITE_ENTRY_ASSERT(expr) \ + if (!(expr)) \ + return svn_error_createf(SVN_ERR_ASSERTION_FAIL, NULL, \ + _("Unable to upgrade '%s' at line %d"), \ + svn_dirent_local_style( \ + svn_dirent_join(root_abspath, \ + local_relpath, \ + scratch_pool), \ + scratch_pool), __LINE__) /* Write the information for ENTRY to WC_DB. The WC_ID, REPOS_ID and REPOS_ROOT will all be used for writing ENTRY. @@ -1663,9 +1737,10 @@ write_entry(struct write_baton **entry_node, replace+copied replace+copied [base|work]+work [base|work]+work */ - SVN_ERR_ASSERT(parent_node || entry->schedule == svn_wc_schedule_normal); - SVN_ERR_ASSERT(!parent_node || parent_node->base - || parent_node->below_work || parent_node->work); + WRITE_ENTRY_ASSERT(parent_node || entry->schedule == svn_wc_schedule_normal); + + WRITE_ENTRY_ASSERT(!parent_node || parent_node->base + || parent_node->below_work || parent_node->work); switch (entry->schedule) { @@ -1710,8 +1785,8 @@ write_entry(struct write_baton **entry_node, BASE node to indicate the not-present node. */ if (entry->deleted) { - SVN_ERR_ASSERT(base_node || below_working_node); - SVN_ERR_ASSERT(!entry->incomplete); + WRITE_ENTRY_ASSERT(base_node || below_working_node); + WRITE_ENTRY_ASSERT(!entry->incomplete); if (base_node) base_node->presence = svn_wc__db_status_not_present; else @@ -1719,8 +1794,8 @@ write_entry(struct write_baton **entry_node, } else if (entry->absent) { - SVN_ERR_ASSERT(base_node && !working_node && !below_working_node); - SVN_ERR_ASSERT(!entry->incomplete); + WRITE_ENTRY_ASSERT(base_node && !working_node && !below_working_node); + WRITE_ENTRY_ASSERT(!entry->incomplete); base_node->presence = svn_wc__db_status_server_excluded; } @@ -1728,16 +1803,10 @@ write_entry(struct write_baton **entry_node, { if (entry->copyfrom_url) { - const char *relpath; - working_node->repos_id = repos_id; - relpath = svn_uri__is_child(this_dir->repos, - entry->copyfrom_url, - result_pool); - if (relpath == NULL) - working_node->repos_relpath = ""; - else - working_node->repos_relpath = relpath; + working_node->repos_relpath = svn_uri_skip_ancestor( + this_dir->repos, entry->copyfrom_url, + result_pool); working_node->revision = entry->copyfrom_rev; working_node->op_depth = svn_wc__db_op_depth_for_upgrade(local_relpath); @@ -1752,6 +1821,17 @@ write_entry(struct write_baton **entry_node, working_node->revision = parent_node->work->revision; working_node->op_depth = parent_node->work->op_depth; } + else if (parent_node->below_work + && parent_node->below_work->repos_relpath) + { + working_node->repos_id = repos_id; + working_node->repos_relpath + = svn_relpath_join(parent_node->below_work->repos_relpath, + svn_relpath_basename(local_relpath, NULL), + result_pool); + working_node->revision = parent_node->below_work->revision; + working_node->op_depth = parent_node->below_work->op_depth; + } else return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL, _("No copyfrom URL for '%s'"), @@ -1827,7 +1907,7 @@ write_entry(struct write_baton **entry_node, scratch_pool), scratch_pool, scratch_pool)); - SVN_ERR_ASSERT(conflict->kind == svn_wc_conflict_kind_tree); + 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. */ @@ -1840,9 +1920,8 @@ write_entry(struct write_baton **entry_node, /* Store in hash to be retrieved when writing the child row. */ key = svn_dirent_skip_ancestor(root_abspath, conflict->local_abspath); - apr_hash_set(tree_conflicts, apr_pstrdup(result_pool, key), - APR_HASH_KEY_STRING, - svn_skel__unparse(new_skel, result_pool)->data); + svn_hash_sets(tree_conflicts, apr_pstrdup(result_pool, key), + svn_skel__unparse(new_skel, result_pool)->data); skel = skel->next; } } @@ -1851,9 +1930,8 @@ write_entry(struct write_baton **entry_node, if (parent_node && parent_node->tree_conflicts) { - const char *tree_conflict_data = apr_hash_get(parent_node->tree_conflicts, - local_relpath, - APR_HASH_KEY_STRING); + const char *tree_conflict_data = + svn_hash_gets(parent_node->tree_conflicts, local_relpath); if (tree_conflict_data) { actual_node = MAYBE_ALLOC(actual_node, scratch_pool); @@ -1862,8 +1940,7 @@ write_entry(struct write_baton **entry_node, /* Reset hash so that we don't write the row again when writing actual-only nodes */ - apr_hash_set(parent_node->tree_conflicts, local_relpath, - APR_HASH_KEY_STRING, NULL); + svn_hash_sets(parent_node->tree_conflicts, local_relpath, NULL); } if (entry->file_external_path != NULL) @@ -1880,8 +1957,8 @@ write_entry(struct write_baton **entry_node, base_node->op_depth = 0; base_node->parent_relpath = parent_relpath; base_node->revision = entry->revision; - base_node->last_mod_time = entry->text_time; - base_node->translated_size = entry->working_size; + base_node->recorded_time = entry->text_time; + base_node->recorded_size = entry->working_size; if (entry->depth != svn_depth_exclude) base_node->depth = entry->depth; @@ -1893,14 +1970,15 @@ write_entry(struct write_baton **entry_node, if (entry->deleted) { - SVN_ERR_ASSERT(base_node->presence == svn_wc__db_status_not_present); + WRITE_ENTRY_ASSERT(base_node->presence + == svn_wc__db_status_not_present); /* ### should be svn_node_unknown, but let's store what we have. */ base_node->kind = entry->kind; } else if (entry->absent) { - SVN_ERR_ASSERT(base_node->presence - == svn_wc__db_status_server_excluded); + WRITE_ENTRY_ASSERT(base_node->presence + == svn_wc__db_status_server_excluded); /* ### should be svn_node_unknown, but let's store what we have. */ base_node->kind = entry->kind; @@ -1933,8 +2011,8 @@ write_entry(struct write_baton **entry_node, else if (entry->incomplete) { /* ### nobody should have set the presence. */ - SVN_ERR_ASSERT(base_node->presence - == svn_wc__db_status_normal); + WRITE_ENTRY_ASSERT(base_node->presence + == svn_wc__db_status_normal); base_node->presence = svn_wc__db_status_incomplete; } } @@ -1995,17 +2073,16 @@ write_entry(struct write_baton **entry_node, if (entry->url != NULL) { - const char *relpath = svn_uri__is_child(this_dir->repos, - entry->url, - result_pool); - base_node->repos_relpath = relpath ? relpath : ""; + base_node->repos_relpath = svn_uri_skip_ancestor( + this_dir->repos, entry->url, + result_pool); } else { - const char *relpath = svn_uri__is_child(this_dir->repos, - this_dir->url, - scratch_pool); - if (relpath == NULL) + const char *relpath = svn_uri_skip_ancestor(this_dir->repos, + this_dir->url, + scratch_pool); + if (relpath == NULL || *relpath == '\0') base_node->repos_relpath = entry->name; else base_node->repos_relpath = @@ -2026,6 +2103,12 @@ write_entry(struct write_baton **entry_node, if (entry->file_external_path) base_node->file_external = TRUE; + /* Switched nodes get an empty iprops cache. */ + if (parent_node + && is_switched(parent_node->base, base_node, scratch_pool)) + base_node->inherited_props + = apr_array_make(scratch_pool, 0, sizeof(svn_prop_inherited_item_t*)); + SVN_ERR(insert_node(sdb, base_node, scratch_pool)); /* We have to insert the lock after the base node, because the node @@ -2057,13 +2140,18 @@ write_entry(struct write_baton **entry_node, 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. */ @@ -2079,13 +2167,37 @@ write_entry(struct write_baton **entry_node, below_working_node->checksum = text_base_info->revert_base.sha1_checksum; } - below_working_node->translated_size = 0; + below_working_node->recorded_size = 0; below_working_node->changed_rev = SVN_INVALID_REVNUM; below_working_node->changed_date = 0; below_working_node->changed_author = NULL; below_working_node->depth = svn_depth_infinity; - below_working_node->last_mod_time = 0; + below_working_node->recorded_time = 0; below_working_node->properties = NULL; + + if (working_node + && entry->schedule == svn_wc_schedule_delete + && working_node->repos_relpath) + { + /* We are lucky, our guesses above are not necessary. The known + correct information is in working. But our op_depth design + expects more information here */ + below_working_node->repos_relpath = working_node->repos_relpath; + below_working_node->repos_id = working_node->repos_id; + below_working_node->revision = working_node->revision; + + /* Nice for 'svn status' */ + below_working_node->changed_rev = entry->cmt_rev; + below_working_node->changed_date = entry->cmt_date; + below_working_node->changed_author = entry->cmt_author; + + /* And now remove it from WORKING, because in wc-ng code + should read it from the lower layer */ + working_node->repos_relpath = NULL; + working_node->repos_id = 0; + working_node->revision = SVN_INVALID_REVNUM; + } + SVN_ERR(insert_node(sdb, below_working_node, scratch_pool)); } @@ -2096,8 +2208,8 @@ write_entry(struct write_baton **entry_node, working_node->local_relpath = local_relpath; working_node->parent_relpath = parent_relpath; working_node->changed_rev = SVN_INVALID_REVNUM; - working_node->last_mod_time = entry->text_time; - working_node->translated_size = entry->working_size; + working_node->recorded_time = entry->text_time; + working_node->recorded_size = entry->working_size; if (entry->depth != svn_depth_exclude) working_node->depth = entry->depth; @@ -2157,8 +2269,8 @@ write_entry(struct write_baton **entry_node, if (entry->incomplete) { /* We shouldn't be overwriting another status. */ - SVN_ERR_ASSERT(working_node->presence - == svn_wc__db_status_normal); + WRITE_ENTRY_ASSERT(working_node->presence + == svn_wc__db_status_normal); working_node->presence = svn_wc__db_status_incomplete; } } @@ -2201,7 +2313,8 @@ write_entry(struct write_baton **entry_node, actual_node->local_relpath = local_relpath; actual_node->parent_relpath = parent_relpath; - SVN_ERR(insert_actual_node(sdb, actual_node, scratch_pool)); + SVN_ERR(insert_actual_node(sdb, db, tmp_entry_abspath, + actual_node, scratch_pool)); } if (entry_node) @@ -2229,6 +2342,8 @@ write_entry(struct write_baton **entry_node, static svn_error_t * write_actual_only_entries(apr_hash_t *tree_conflicts, svn_sqlite__db_t *sdb, + svn_wc__db_t *db, + const char *wri_abspath, apr_int64_t wc_id, const char *parent_relpath, apr_pool_t *scratch_pool) @@ -2247,7 +2362,8 @@ write_actual_only_entries(apr_hash_t *tree_conflicts, actual_node->parent_relpath = parent_relpath; actual_node->tree_conflict_data = svn__apr_hash_index_val(hi); - SVN_ERR(insert_actual_node(sdb, actual_node, scratch_pool)); + SVN_ERR(insert_actual_node(sdb, db, wri_abspath, actual_node, + scratch_pool)); } return SVN_NO_ERROR; @@ -2275,8 +2391,7 @@ svn_wc__write_upgraded_entries(void **dir_baton, struct write_baton *dir_node; /* Get a copy of the "this dir" entry for comparison purposes. */ - 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); /* If there is no "this dir" entry, something is wrong. */ if (! this_dir) @@ -2307,7 +2422,7 @@ svn_wc__write_upgraded_entries(void **dir_baton, const svn_wc_entry_t *this_entry = svn__apr_hash_index_val(hi); const char *child_abspath, *child_relpath; svn_wc__text_base_info_t *text_base_info - = apr_hash_get(text_bases_info, name, APR_HASH_KEY_STRING); + = svn_hash_gets(text_bases_info, name); svn_pool_clear(iterpool); @@ -2329,8 +2444,9 @@ svn_wc__write_upgraded_entries(void **dir_baton, } if (dir_node->tree_conflicts) - SVN_ERR(write_actual_only_entries(dir_node->tree_conflicts, sdb, - wc_id, dir_relpath, iterpool)); + SVN_ERR(write_actual_only_entries(dir_node->tree_conflicts, sdb, db, + new_root_abspath, wc_id, dir_relpath, + iterpool)); *dir_baton = dir_node; svn_pool_destroy(iterpool); @@ -2425,14 +2541,14 @@ walker_helper(const char *dirpath, svn_error_t *err; svn_wc__db_t *db = svn_wc__adm_get_db(adm_access); - err = svn_wc_entries_read(&entries, adm_access, show_hidden, pool); + err = svn_wc__entries_read_internal(&entries, adm_access, show_hidden, + pool); if (err) SVN_ERR(walk_callbacks->handle_error(dirpath, err, walk_baton, pool)); /* As promised, always return the '.' entry first. */ - dot_entry = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, - APR_HASH_KEY_STRING); + dot_entry = svn_hash_gets(entries, SVN_WC_ENTRY_THIS_DIR); if (! dot_entry) return walk_callbacks->handle_error (dirpath, svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL, @@ -2544,7 +2660,7 @@ svn_wc_walk_entries3(const char *path, const char *local_abspath; svn_wc__db_t *db = svn_wc__adm_get_db(adm_access); svn_error_t *err; - svn_wc__db_kind_t kind; + svn_node_kind_t kind; svn_depth_t depth; SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); @@ -2568,7 +2684,7 @@ svn_wc_walk_entries3(const char *path, walk_baton, pool); } - if (kind == svn_wc__db_kind_file || depth == svn_depth_exclude) + if (kind == svn_node_file || depth == svn_depth_exclude) { const svn_wc_entry_t *entry; @@ -2610,7 +2726,7 @@ svn_wc_walk_entries3(const char *path, return SVN_NO_ERROR; } - if (kind == svn_wc__db_kind_dir) + if (kind == svn_node_dir) return walker_helper(path, adm_access, walk_callbacks, walk_baton, walk_depth, show_hidden, cancel_func, cancel_baton, pool); |