summaryrefslogtreecommitdiff
path: root/subversion/libsvn_wc/entries.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_wc/entries.c')
-rw-r--r--subversion/libsvn_wc/entries.c536
1 files changed, 328 insertions, 208 deletions
diff --git a/subversion/libsvn_wc/entries.c b/subversion/libsvn_wc/entries.c
index 24dae50..1be6a8b 100644
--- a/subversion/libsvn_wc/entries.c
+++ b/subversion/libsvn_wc/entries.c
@@ -45,9 +45,14 @@
#include "wc_db.h"
#include "wc-queries.h" /* for STMT_* */
+#define SVN_WC__I_AM_WC_DB
+
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
#include "private/svn_sqlite.h"
+#include "token-map.h"
+
+#include "wc_db_private.h"
#define MAYBE_ALLOC(x,p) ((x) ? (x) : apr_pcalloc((p), sizeof(*(x))))
@@ -213,6 +218,8 @@ get_info_for_deleted(svn_wc_entry_t *entry,
svn_wc__db_lock_t **lock,
svn_wc__db_t *db,
const char *entry_abspath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *entry_relpath,
const svn_wc_entry_t *parent_entry,
svn_boolean_t have_base,
svn_boolean_t have_more_work,
@@ -221,12 +228,13 @@ get_info_for_deleted(svn_wc_entry_t *entry,
{
if (have_base && !have_more_work)
{
+ apr_int64_t repos_id;
/* This is the delete of a BASE node */
- SVN_ERR(svn_wc__db_base_get_info(NULL, kind,
+ SVN_ERR(svn_wc__db_base_get_info_internal(
+ NULL, kind,
&entry->revision,
repos_relpath,
- &entry->repos,
- &entry->uuid,
+ &repos_id,
&entry->cmt_rev,
&entry->cmt_date,
&entry->cmt_author,
@@ -236,16 +244,18 @@ get_info_for_deleted(svn_wc_entry_t *entry,
lock,
&entry->has_props, NULL,
NULL,
- db,
- entry_abspath,
+ wcroot, entry_relpath,
result_pool,
scratch_pool));
+ SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
+ wcroot, repos_id, result_pool));
}
else
{
- const char *work_del_abspath;
+ const char *work_del_relpath;
const char *parent_repos_relpath;
- const char *parent_abspath;
+ const char *parent_relpath;
+ apr_int64_t repos_id;
/* This is a deleted child of a copy/move-here,
so we need to scan up the WORKING tree to find the root of
@@ -265,30 +275,33 @@ get_info_for_deleted(svn_wc_entry_t *entry,
scratch_pool));
/* working_size and text_time unavailable */
- SVN_ERR(svn_wc__db_scan_deletion(NULL,
+ SVN_ERR(svn_wc__db_scan_deletion_internal(
NULL,
- &work_del_abspath, NULL,
- db, entry_abspath,
+ NULL,
+ &work_del_relpath, NULL,
+ wcroot, entry_relpath,
scratch_pool, scratch_pool));
- SVN_ERR_ASSERT(work_del_abspath != NULL);
- parent_abspath = svn_dirent_dirname(work_del_abspath, scratch_pool);
+ SVN_ERR_ASSERT(work_del_relpath != NULL);
+ parent_relpath = svn_relpath_dirname(work_del_relpath, scratch_pool);
/* The parent directory of the delete root must be added, so we
can find the required information there */
- SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
+ SVN_ERR(svn_wc__db_scan_addition_internal(
+ NULL, NULL,
&parent_repos_relpath,
- &entry->repos,
- &entry->uuid,
- NULL, NULL, NULL, NULL,
- db, parent_abspath,
+ &repos_id,
+ NULL, NULL, NULL,
+ wcroot, parent_relpath,
result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
+ wcroot, repos_id, result_pool));
/* Now glue it all together */
*repos_relpath = svn_relpath_join(parent_repos_relpath,
- svn_dirent_is_child(parent_abspath,
- entry_abspath,
- NULL),
+ svn_relpath_skip_ancestor(
+ parent_relpath,
+ entry_relpath),
result_pool);
@@ -297,11 +310,12 @@ get_info_for_deleted(svn_wc_entry_t *entry,
if (have_base)
{
svn_wc__db_status_t status;
- SVN_ERR(svn_wc__db_base_get_info(&status, NULL, &entry->revision,
+ SVN_ERR(svn_wc__db_base_get_info_internal(
+ &status, NULL, &entry->revision,
NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, lock, NULL, NULL,
+ NULL, NULL, lock, NULL, NULL,
NULL,
- db, entry_abspath,
+ wcroot, entry_relpath,
result_pool, scratch_pool));
if (status == svn_wc__db_status_not_present)
@@ -346,7 +360,7 @@ write_tree_conflicts(const char **conflict_data,
{
svn_skel_t *c_skel;
- SVN_ERR(svn_wc__serialize_conflict(&c_skel, svn__apr_hash_index_val(hi),
+ SVN_ERR(svn_wc__serialize_conflict(&c_skel, apr_hash_this_val(hi),
pool, pool));
svn_skel__prepend(c_skel, skel);
}
@@ -369,12 +383,17 @@ write_tree_conflicts(const char **conflict_data,
If this node is "this dir", then PARENT_ENTRY should be NULL. Otherwise,
it should refer to the entry for the child's parent directory.
+ ### All database read operations should really use wcroot, dir_relpath,
+ as that restores obstruction compatibility with <= 1.6.0
+ but that has been the case since the introduction of WC-NG in 1.7.0
+
Temporary allocations are made in SCRATCH_POOL. */
static svn_error_t *
read_one_entry(const svn_wc_entry_t **new_entry,
svn_wc__db_t *db,
- apr_int64_t wc_id,
const char *dir_abspath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *dir_relpath,
const char *name,
const svn_wc_entry_t *parent_entry,
apr_pool_t *result_pool,
@@ -387,24 +406,28 @@ read_one_entry(const svn_wc_entry_t **new_entry,
const svn_checksum_t *checksum;
svn_filesize_t translated_size;
svn_wc_entry_t *entry = alloc_entry(result_pool);
+ const char *entry_relpath;
const char *entry_abspath;
+ apr_int64_t repos_id;
+ apr_int64_t original_repos_id;
const char *original_repos_relpath;
const char *original_root_url;
svn_boolean_t conflicted;
svn_boolean_t have_base;
svn_boolean_t have_more_work;
+ svn_boolean_t op_root;
- entry->name = name;
+ entry->name = apr_pstrdup(result_pool, name);
+ entry_relpath = svn_relpath_join(dir_relpath, entry->name, scratch_pool);
entry_abspath = svn_dirent_join(dir_abspath, entry->name, scratch_pool);
- SVN_ERR(svn_wc__db_read_info(
+ SVN_ERR(svn_wc__db_read_info_internal(
&status,
&kind,
&entry->revision,
&repos_relpath,
- &entry->repos,
- &entry->uuid,
+ &repos_id,
&entry->cmt_rev,
&entry->cmt_date,
&entry->cmt_author,
@@ -412,24 +435,27 @@ read_one_entry(const svn_wc_entry_t **new_entry,
&checksum,
NULL,
&original_repos_relpath,
- &original_root_url,
- NULL,
+ &original_repos_id,
&entry->copyfrom_rev,
&lock,
&translated_size,
&entry->text_time,
&entry->changelist,
&conflicted,
- NULL /* op_root */,
+ &op_root,
&entry->has_props /* have_props */,
&entry->has_prop_mods /* props_mod */,
&have_base,
&have_more_work,
NULL /* have_work */,
- db,
- entry_abspath,
- result_pool,
- scratch_pool));
+ wcroot, entry_relpath,
+ result_pool, scratch_pool));
+
+ SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
+ wcroot, repos_id, result_pool));
+ SVN_ERR(svn_wc__db_fetch_repos_info(&original_root_url, NULL,
+ wcroot, original_repos_id,
+ result_pool));
if (entry->has_prop_mods)
entry->has_props = TRUE;
@@ -457,9 +483,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__read_conflicts(&child_conflicts,
+ SVN_ERR(svn_wc__read_conflicts(&child_conflicts, NULL,
db, child_abspath,
FALSE /* create tempfiles */,
+ TRUE /* tree_conflicts_only */,
scratch_pool, scratch_pool));
for (j = 0; j < child_conflicts->nelts; j++)
@@ -493,13 +520,15 @@ read_one_entry(const svn_wc_entry_t **new_entry,
/* Grab inherited repository information, if necessary. */
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));
+ SVN_ERR(svn_wc__db_base_get_info_internal(
+ NULL, NULL, NULL, &repos_relpath,
+ &repos_id, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL,
+ wcroot, entry_relpath,
+ result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
+ wcroot, repos_id, result_pool));
}
entry->incomplete = (status == svn_wc__db_status_incomplete);
@@ -519,13 +548,14 @@ read_one_entry(const svn_wc_entry_t **new_entry,
entry->copied = FALSE;
else
{
- const char *work_del_abspath;
- SVN_ERR(svn_wc__db_scan_deletion(NULL, NULL,
- &work_del_abspath, NULL,
- db, entry_abspath,
+ const char *work_del_relpath;
+ SVN_ERR(svn_wc__db_scan_deletion_internal(
+ NULL, NULL,
+ &work_del_relpath, NULL,
+ wcroot, entry_relpath,
scratch_pool, scratch_pool));
- if (work_del_abspath)
+ if (work_del_relpath)
entry->copied = TRUE;
}
@@ -563,13 +593,14 @@ read_one_entry(const svn_wc_entry_t **new_entry,
/* ENTRY->REVISION is overloaded. When a node is schedule-add
or -replace, then REVISION refers to the BASE node's revision
that is being overwritten. We need to fetch it now. */
- SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL,
+ SVN_ERR(svn_wc__db_base_get_info_internal(
+ &base_status, NULL,
&entry->revision,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- db, entry_abspath,
+ NULL, NULL, NULL,
+ wcroot, entry_relpath,
scratch_pool,
scratch_pool));
@@ -603,18 +634,27 @@ read_one_entry(const svn_wc_entry_t **new_entry,
have important data. Set up stuff to kill that idea off,
and finish up this entry. */
{
- SVN_ERR(svn_wc__db_scan_addition(&work_status,
- &op_root_abspath,
+ const char *op_root_relpath;
+ SVN_ERR(svn_wc__db_scan_addition_internal(
+ &work_status,
+ &op_root_relpath,
&repos_relpath,
- &entry->repos,
- &entry->uuid,
+ &repos_id,
&scanned_original_relpath,
- NULL, NULL, /* original_root|uuid */
+ NULL /* original_repos_id */,
&original_revision,
- db,
- entry_abspath,
+ wcroot, entry_relpath,
result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_fetch_repos_info(&entry->repos, &entry->uuid,
+ wcroot, repos_id, result_pool));
+
+ if (!op_root_relpath)
+ op_root_abspath = NULL;
+ else
+ op_root_abspath = svn_dirent_join(wcroot->abspath, op_root_relpath,
+ scratch_pool);
+
/* In wc.db we want to keep the valid revision of the not-present
BASE_REV, but when we used entries we set the revision to 0
when adding a new node over a not present base node. */
@@ -633,7 +673,7 @@ 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. */
}
- /* For backwards-compatiblity purposes we treat moves just like
+ /* For backwards-compatibility 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)
@@ -675,10 +715,12 @@ read_one_entry(const svn_wc_entry_t **new_entry,
mixed-revision situation. */
if (!is_copied_child)
{
- const char *parent_abspath;
+ const char *parent_relpath;
svn_error_t *err;
const char *parent_repos_relpath;
const char *parent_root_url;
+ apr_int64_t parent_repos_id;
+ const char *op_root_relpath;
/* When we insert entries into the database, we will
construct additional copyfrom records for mixed-revision
@@ -705,15 +747,16 @@ read_one_entry(const svn_wc_entry_t **new_entry,
Note that the parent could be added/copied/moved-here.
There is no way for it to be deleted/moved-away and
have *this* node appear as copied. */
- parent_abspath = svn_dirent_dirname(entry_abspath,
- scratch_pool);
- err = svn_wc__db_scan_addition(NULL,
- &op_root_abspath,
- NULL, NULL, NULL,
- &parent_repos_relpath,
- &parent_root_url,
+ parent_relpath = svn_relpath_dirname(entry_relpath,
+ scratch_pool);
+ err = svn_wc__db_scan_addition_internal(
+ NULL,
+ &op_root_relpath,
NULL, NULL,
- db, parent_abspath,
+ &parent_repos_relpath,
+ &parent_repos_id,
+ NULL,
+ wcroot, parent_relpath,
scratch_pool,
scratch_pool);
if (err)
@@ -721,10 +764,24 @@ read_one_entry(const svn_wc_entry_t **new_entry,
if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
return svn_error_trace(err);
svn_error_clear(err);
+ op_root_abspath = NULL;
+ parent_repos_relpath = NULL;
+ parent_root_url = NULL;
+ }
+ else
+ {
+ SVN_ERR(svn_wc__db_fetch_repos_info(&parent_root_url, NULL,
+ wcroot, parent_repos_id,
+ scratch_pool));
+ op_root_abspath = svn_dirent_join(wcroot->abspath,
+ op_root_relpath,
+ scratch_pool);
}
- else if (parent_root_url != NULL
+
+ if (parent_root_url != NULL
&& strcmp(original_root_url, parent_root_url) == 0)
{
+
const char *relpath_to_entry = svn_dirent_is_child(
op_root_abspath, entry_abspath, NULL);
const char *entry_repos_relpath = svn_relpath_join(
@@ -827,6 +884,7 @@ read_one_entry(const svn_wc_entry_t **new_entry,
&checksum,
&lock,
db, entry_abspath,
+ wcroot, entry_relpath,
parent_entry,
have_base, have_more_work,
result_pool, scratch_pool));
@@ -869,7 +927,7 @@ read_one_entry(const svn_wc_entry_t **new_entry,
/* We got a SHA-1, get the corresponding MD-5. */
if (checksum->kind != svn_checksum_md5)
SVN_ERR(svn_wc__db_pristine_get_md5(&checksum, db,
- entry_abspath, checksum,
+ dir_abspath, checksum,
scratch_pool, scratch_pool));
SVN_ERR_ASSERT(checksum->kind == svn_checksum_md5);
@@ -881,8 +939,9 @@ read_one_entry(const svn_wc_entry_t **new_entry,
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));
+ SVN_ERR(svn_wc__db_read_conflict_internal(&conflict, NULL, NULL,
+ wcroot, entry_relpath,
+ scratch_pool, scratch_pool));
SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, &text_conflicted,
&prop_conflicted, NULL,
@@ -955,7 +1014,9 @@ read_one_entry(const svn_wc_entry_t **new_entry,
static svn_error_t *
read_entries_new(apr_hash_t **result_entries,
svn_wc__db_t *db,
- const char *local_abspath,
+ const char *dir_abspath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *dir_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -964,11 +1025,12 @@ read_entries_new(apr_hash_t **result_entries,
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
int i;
const svn_wc_entry_t *parent_entry;
- apr_int64_t wc_id = 1; /* ### hacky. should remove. */
entries = apr_hash_make(result_pool);
- SVN_ERR(read_one_entry(&parent_entry, db, wc_id, local_abspath,
+ SVN_ERR(read_one_entry(&parent_entry,
+ db, dir_abspath,
+ wcroot, dir_relpath,
"" /* name */,
NULL /* parent_entry */,
result_pool, iterpool));
@@ -977,8 +1039,8 @@ read_entries_new(apr_hash_t **result_entries,
/* Use result_pool so that the child names (used by reference, rather
than copied) appear in result_pool. */
SVN_ERR(svn_wc__db_read_children(&children, db,
- local_abspath,
- result_pool, iterpool));
+ dir_abspath,
+ scratch_pool, iterpool));
for (i = children->nelts; i--; )
{
const char *name = APR_ARRAY_IDX(children, i, const char *);
@@ -987,7 +1049,9 @@ read_entries_new(apr_hash_t **result_entries,
svn_pool_clear(iterpool);
SVN_ERR(read_one_entry(&entry,
- db, wc_id, local_abspath, name, parent_entry,
+ db, dir_abspath,
+ wcroot, dir_relpath,
+ name, parent_entry,
result_pool, iterpool));
svn_hash_sets(entries, entry->name, entry);
}
@@ -1000,28 +1064,20 @@ read_entries_new(apr_hash_t **result_entries,
}
-/* Read a pair of entries from wc_db in the directory DIR_ABSPATH. Return
- the directory's entry in *PARENT_ENTRY and NAME's entry in *ENTRY. The
- two returned pointers will be the same if NAME=="" ("this dir").
-
- The parent entry must exist.
-
- The requested entry MAY exist. If it does not, then NULL will be returned.
-
- The resulting entries are allocated in RESULT_POOL, and all temporary
- allocations are made in SCRATCH_POOL. */
static svn_error_t *
-read_entry_pair(const svn_wc_entry_t **parent_entry,
- const svn_wc_entry_t **entry,
- svn_wc__db_t *db,
- const char *dir_abspath,
- const char *name,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+read_entry_pair_txn(const svn_wc_entry_t **parent_entry,
+ const svn_wc_entry_t **entry,
+ svn_wc__db_t *db,
+ const char *dir_abspath,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *dir_relpath,
+ const char *name,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_int64_t wc_id = 1; /* ### hacky. should remove. */
-
- SVN_ERR(read_one_entry(parent_entry, db, wc_id, dir_abspath,
+ SVN_ERR(read_one_entry(parent_entry,
+ db, dir_abspath,
+ wcroot, dir_relpath,
"" /* name */,
NULL /* parent_entry */,
result_pool, scratch_pool));
@@ -1073,7 +1129,9 @@ read_entry_pair(const svn_wc_entry_t **parent_entry,
svn_error_t *err;
err = read_one_entry(entry,
- db, wc_id, dir_abspath, name, *parent_entry,
+ db, dir_abspath,
+ wcroot, dir_relpath,
+ name, *parent_entry,
result_pool, scratch_pool);
if (err)
{
@@ -1096,28 +1154,76 @@ read_entry_pair(const svn_wc_entry_t **parent_entry,
return SVN_NO_ERROR;
}
+/* Read a pair of entries from wc_db in the directory DIR_ABSPATH. Return
+ the directory's entry in *PARENT_ENTRY and NAME's entry in *ENTRY. The
+ two returned pointers will be the same if NAME=="" ("this dir").
+
+ The parent entry must exist.
+
+ The requested entry MAY exist. If it does not, then NULL will be returned.
+
+ The resulting entries are allocated in RESULT_POOL, and all temporary
+ allocations are made in SCRATCH_POOL. */
+static svn_error_t *
+read_entry_pair(const svn_wc_entry_t **parent_entry,
+ const svn_wc_entry_t **entry,
+ svn_wc__db_t *db,
+ const char *dir_abspath,
+ const char *name,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *dir_relpath;
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &dir_relpath,
+ db, dir_abspath,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_WC__DB_WITH_TXN(read_entry_pair_txn(parent_entry, entry,
+ db, dir_abspath,
+ wcroot, dir_relpath,
+ name,
+ result_pool, scratch_pool),
+ wcroot);
+
+ return SVN_NO_ERROR;
+}
/* */
static svn_error_t *
read_entries(apr_hash_t **entries,
svn_wc__db_t *db,
- const char *wcroot_abspath,
+ const char *dir_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *dir_relpath;
int wc_format;
- SVN_ERR(svn_wc__db_temp_get_format(&wc_format, db, wcroot_abspath,
+ SVN_ERR(svn_wc__db_temp_get_format(&wc_format, db, dir_abspath,
scratch_pool));
if (wc_format < SVN_WC__WC_NG_VERSION)
return svn_error_trace(svn_wc__read_entries_old(entries,
- wcroot_abspath,
+ dir_abspath,
result_pool,
scratch_pool));
- return svn_error_trace(read_entries_new(entries, db, wcroot_abspath,
- result_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &dir_relpath,
+ db, dir_abspath,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ SVN_WC__DB_WITH_TXN(read_entries_new(entries,
+ db, dir_abspath,
+ wcroot, dir_relpath,
+ result_pool, scratch_pool),
+ wcroot);
+
+ return SVN_NO_ERROR;
}
@@ -1342,7 +1448,7 @@ prune_deleted(apr_hash_t **entries_pruned,
svn_boolean_t hidden;
SVN_ERR(svn_wc__entry_is_hidden(&hidden,
- svn__apr_hash_index_val(hi)));
+ apr_hash_this_val(hi)));
if (hidden)
break;
}
@@ -1360,8 +1466,8 @@ prune_deleted(apr_hash_t **entries_pruned,
hi;
hi = apr_hash_next(hi))
{
- const void *key = svn__apr_hash_index_key(hi);
- const svn_wc_entry_t *entry = svn__apr_hash_index_val(hi);
+ const void *key = apr_hash_this_key(hi);
+ const svn_wc_entry_t *entry = apr_hash_this_val(hi);
svn_boolean_t hidden;
SVN_ERR(svn_wc__entry_is_hidden(&hidden, entry));
@@ -1372,25 +1478,6 @@ prune_deleted(apr_hash_t **entries_pruned,
return SVN_NO_ERROR;
}
-struct entries_read_baton_t
-{
- apr_hash_t **new_entries;
- svn_wc__db_t *db;
- const char *local_abspath;
- apr_pool_t *result_pool;
-};
-
-static svn_error_t *
-entries_read_txn(void *baton, svn_sqlite__db_t *db, apr_pool_t *scratch_pool)
-{
- struct entries_read_baton_t *erb = baton;
-
- SVN_ERR(read_entries(erb->new_entries, erb->db, erb->local_abspath,
- erb->result_pool, scratch_pool));
-
- return NULL;
-}
-
svn_error_t *
svn_wc__entries_read_internal(apr_hash_t **entries,
svn_wc_adm_access_t *adm_access,
@@ -1405,21 +1492,9 @@ svn_wc__entries_read_internal(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_internal(adm_access);
- svn_sqlite__db_t *sdb;
- struct entries_read_baton_t erb;
-
- /* ### Use the borrow DB api to handle all calls in a single read
- ### transaction. This api is used extensively in our test suite
- ### via the entries-read application. */
- SVN_ERR(svn_wc__db_temp_borrow_sdb(&sdb, db, local_abspath, pool));
-
- erb.db = db;
- erb.local_abspath = local_abspath;
- erb.new_entries = &new_entries;
- erb.result_pool = result_pool;
-
- SVN_ERR(svn_sqlite__with_lock(sdb, entries_read_txn, &erb, pool));
+ SVN_ERR(read_entries(&new_entries, db, local_abspath,
+ result_pool, pool));
svn_wc__adm_access_set_entries(adm_access, new_entries);
}
@@ -1452,23 +1527,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 +1560,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 +1581,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 +1878,10 @@ write_entry(struct write_baton **entry_node,
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 +1891,37 @@ write_entry(struct write_baton **entry_node,
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 +1935,29 @@ write_entry(struct write_baton **entry_node,
_("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)
@@ -1892,7 +2013,7 @@ write_entry(struct write_baton **entry_node,
scratch_pool);
tree_conflicts = apr_hash_make(result_pool);
skel = skel->children;
- while(skel)
+ while (skel)
{
svn_wc_conflict_description2_t *conflict;
svn_skel_t *new_skel;
@@ -1909,11 +2030,6 @@ write_entry(struct write_baton **entry_node,
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));
@@ -2295,6 +2411,11 @@ write_entry(struct write_baton **entry_node,
{
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
@@ -2358,9 +2479,9 @@ write_actual_only_entries(apr_hash_t *tree_conflicts,
actual_node = MAYBE_ALLOC(actual_node, scratch_pool);
actual_node->wc_id = wc_id;
- actual_node->local_relpath = svn__apr_hash_index_key(hi);
+ actual_node->local_relpath = apr_hash_this_key(hi);
actual_node->parent_relpath = parent_relpath;
- actual_node->tree_conflict_data = svn__apr_hash_index_val(hi);
+ actual_node->tree_conflict_data = apr_hash_this_val(hi);
SVN_ERR(insert_actual_node(sdb, db, wri_abspath, actual_node,
scratch_pool));
@@ -2418,8 +2539,8 @@ svn_wc__write_upgraded_entries(void **dir_baton,
for (hi = apr_hash_first(scratch_pool, entries); hi;
hi = apr_hash_next(hi))
{
- const char *name = svn__apr_hash_index_key(hi);
- const svn_wc_entry_t *this_entry = svn__apr_hash_index_val(hi);
+ const char *name = apr_hash_this_key(hi);
+ const svn_wc_entry_t *this_entry = apr_hash_this_val(hi);
const char *child_abspath, *child_relpath;
svn_wc__text_base_info_t *text_base_info
= svn_hash_gets(text_bases_info, name);
@@ -2573,8 +2694,8 @@ walker_helper(const char *dirpath,
/* Loop over each of the other entries. */
for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
{
- const char *name = svn__apr_hash_index_key(hi);
- const svn_wc_entry_t *current_entry = svn__apr_hash_index_val(hi);
+ const char *name = apr_hash_this_key(hi);
+ const svn_wc_entry_t *current_entry = apr_hash_this_val(hi);
const char *entrypath;
const char *entry_abspath;
svn_boolean_t hidden;
@@ -2661,11 +2782,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,
@@ -2684,7 +2805,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;
@@ -2693,27 +2816,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)
+ if (!show_hidden
+ && (status == svn_wc__db_status_not_present
+ || status == svn_wc__db_status_excluded
+ || status == svn_wc__db_status_server_excluded))
{
- 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);
- }
+ /* 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,