You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/15 21:32:38 UTC
svn commit: r997472 [21/41] - in /subversion/branches/py-tests-as-modules:
./ build/ build/ac-macros/ build/generator/ build/generator/templates/
contrib/server-side/ notes/ notes/tree-conflicts/ notes/wc-ng/
subversion/bindings/javahl/native/ subversi...
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.c Wed Sep 15 19:32:26 2010
@@ -158,22 +158,6 @@ svn_wc__entry_is_hidden(svn_boolean_t *h
}
-/* */
-static svn_error_t *
-fetch_wc_id(apr_int64_t *wc_id, svn_sqlite__db_t *sdb)
-{
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WCROOT_NULL));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- if (!have_row)
- return svn_error_create(SVN_ERR_WC_DB_ERROR, NULL, _("No WC table entry"));
- *wc_id = svn_sqlite__column_int(stmt, 0);
- return svn_error_return(svn_sqlite__reset(stmt));
-}
-
-
/* Hit the database to check the file external information for the given
entry. The entry will be modified in place. */
static svn_error_t *
@@ -287,8 +271,7 @@ get_base_info_for_deleted(svn_wc_entry_t
NULL, NULL, NULL, NULL, NULL, NULL,
db, parent_abspath,
scratch_pool, scratch_pool));
- if (parent_status == svn_wc__db_status_added
- || parent_status == svn_wc__db_status_obstructed_add)
+ if (parent_status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(NULL, NULL,
&parent_repos_relpath,
&entry->repos,
@@ -420,8 +403,7 @@ get_base_info_for_deleted(svn_wc_entry_t
NULL, NULL, NULL, NULL, NULL, NULL,
db, parent_abspath,
scratch_pool, scratch_pool));
- if (parent_status == svn_wc__db_status_added
- || parent_status == svn_wc__db_status_obstructed_add)
+ if (parent_status == svn_wc__db_status_added)
SVN_ERR(svn_wc__db_scan_addition(&parent_status,
NULL,
NULL, NULL, NULL,
@@ -664,33 +646,24 @@ read_one_entry(const svn_wc_entry_t **ne
entry->incomplete = (status == svn_wc__db_status_incomplete);
}
}
- else if (status == svn_wc__db_status_deleted
- || status == svn_wc__db_status_obstructed_delete)
+ else if (status == svn_wc__db_status_deleted)
{
+ svn_node_kind_t path_kind;
/* ### we don't have to worry about moves, so this is a delete. */
entry->schedule = svn_wc_schedule_delete;
- /* ### keep_local ... ugh. hacky. */
- /* We only read keep_local in the directory itself, because we
- can't rely on the actual record being available in the parent
- stub when the directory is recorded as deleted in the directory
- itself. (This last value is the status that brought us in this
- if block).
-
- This is safe because we will only write this flag in the
- directory itself (see mark_deleted() in adm_ops.c), and also
- because we will never use keep_local in the final version of
- WC-NG. With a central db and central pristine store we can
- remove working copy directories directly. So any left over
- directories after the delete operation are always kept locally.
- */
- if (*entry->name == '\0')
- SVN_ERR(svn_wc__db_temp_determine_keep_local(&entry->keep_local,
- db, entry_abspath,
- scratch_pool));
+ /* If there is still a directory on-disk we keep it, if not it is
+ already deleted. Simple, isn't it?
+
+ Before single-db we had to keep the administative area alive until
+ after the commit really deletes it. Setting keep alive stopped the
+ commit processing from deleting the directory. We don't delete it
+ any more, so all we have to do is provide some 'sane' value.
+ */
+ SVN_ERR(svn_io_check_path(entry_abspath, &path_kind, scratch_pool));
+ entry->keep_local = (path_kind == svn_node_dir);
}
- else if (status == svn_wc__db_status_added
- || status == svn_wc__db_status_obstructed_add)
+ else if (status == svn_wc__db_status_added)
{
svn_wc__db_status_t work_status;
const char *op_root_abspath;
@@ -772,16 +745,7 @@ read_one_entry(const svn_wc_entry_t **ne
&& !SVN_IS_VALID_REVNUM(entry->cmt_rev))
entry->revision = 0;
- if (status == svn_wc__db_status_obstructed_add)
- entry->revision = SVN_INVALID_REVNUM;
-
- /* ### when we're reading a directory that is not present,
- ### then it must be "normal" rather than "add". */
- if (*entry->name == '\0'
- && status == svn_wc__db_status_obstructed_add)
- entry->schedule = svn_wc_schedule_normal;
- else
- entry->schedule = svn_wc_schedule_add;
+ entry->schedule = svn_wc_schedule_add;
}
}
@@ -789,13 +753,6 @@ read_one_entry(const svn_wc_entry_t **ne
then we cannot begin a scan for data. The original node may
have important data. Set up stuff to kill that idea off,
and finish up this entry. */
- if (status == svn_wc__db_status_obstructed_add)
- {
- entry->cmt_rev = SVN_INVALID_REVNUM;
- work_status = svn_wc__db_status_normal;
- scanned_original_relpath = NULL;
- }
- else
{
SVN_ERR(svn_wc__db_scan_addition(&work_status,
&op_root_abspath,
@@ -993,12 +950,6 @@ read_one_entry(const svn_wc_entry_t **ne
entry->schedule = svn_wc_schedule_normal;
entry->deleted = TRUE;
}
- else if (status == svn_wc__db_status_obstructed)
- {
- /* ### set some values that should (hopefully) let this directory
- ### be usable. */
- entry->revision = SVN_INVALID_REVNUM;
- }
else if (status == svn_wc__db_status_absent)
{
entry->absent = TRUE;
@@ -1051,13 +1002,9 @@ read_one_entry(const svn_wc_entry_t **ne
*/
SVN_ERR_ASSERT(repos_relpath != NULL
|| entry->schedule == svn_wc_schedule_delete
- || status == svn_wc__db_status_obstructed
- || status == svn_wc__db_status_obstructed_add
- || status == svn_wc__db_status_obstructed_delete
|| status == svn_wc__db_status_not_present
|| status == svn_wc__db_status_absent
- || status == svn_wc__db_status_excluded
- );
+ || status == svn_wc__db_status_excluded);
if (repos_relpath)
entry->url = svn_path_url_add_component2(entry->repos,
repos_relpath,
@@ -1307,7 +1254,7 @@ read_entries(apr_hash_t **entries,
which the entry information is located, and *ENTRY_NAME to the entry name
to access that entry.
- KIND and NEED_PARENT_STUB are as in svn_wc__get_entry().
+ KIND is as in svn_wc__get_entry().
Return the results in RESULT_POOL and use SCRATCH_POOL for temporary
allocations. */
@@ -1317,16 +1264,12 @@ get_entry_access_info(const char **adm_a
svn_wc__db_t *db,
const char *local_abspath,
svn_node_kind_t kind,
- svn_boolean_t need_parent_stub,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_wc_adm_access_t *adm_access;
svn_boolean_t read_from_subdir = FALSE;
- /* Can't ask for the parent stub if the node is a file. */
- SVN_ERR_ASSERT(!need_parent_stub || kind != svn_node_file);
-
/* If the caller didn't know the node kind, then stat the path. Maybe
it is really there, and we can speed up the steps below. */
if (kind == svn_node_unknown)
@@ -1370,10 +1313,10 @@ get_entry_access_info(const char **adm_a
{
/* We found a directory for this UNKNOWN node. Determine whether
we need to read inside it. */
- read_from_subdir = !need_parent_stub;
+ read_from_subdir = TRUE;
}
}
- else if (kind == svn_node_dir && !need_parent_stub)
+ else if (kind == svn_node_dir)
{
read_from_subdir = TRUE;
}
@@ -1390,7 +1333,7 @@ get_entry_access_info(const char **adm_a
/* FILE node needs to read the parent directory. Or a DIR node
needs to read from the parent to get at the stub entry. Or this
is an UNKNOWN node, and we need to examine the parent. */
- svn_dirent_split(local_abspath, adm_abspath, entry_name, result_pool);
+ svn_dirent_split(adm_abspath, entry_name, local_abspath, result_pool);
}
return SVN_NO_ERROR;
@@ -1403,19 +1346,14 @@ svn_wc__get_entry(const svn_wc_entry_t *
const char *local_abspath,
svn_boolean_t allow_unversioned,
svn_node_kind_t kind,
- svn_boolean_t need_parent_stub,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const char *dir_abspath;
const char *entry_name;
- /* Can't ask for the parent stub if the node is a file. */
- SVN_ERR_ASSERT(!need_parent_stub || kind != svn_node_file);
-
SVN_ERR(get_entry_access_info(&dir_abspath, &entry_name, db, local_abspath,
- kind, need_parent_stub, scratch_pool,
- scratch_pool));
+ kind, scratch_pool, scratch_pool));
{
const svn_wc_entry_t *parent_entry;
@@ -1464,8 +1402,7 @@ svn_wc__get_entry(const svn_wc_entry_t *
Redo the fetch, but "insist" we are trying to find a file.
This will read from the parent directory of the "file". */
err = svn_wc__get_entry(entry, db, local_abspath, allow_unversioned,
- svn_node_file, FALSE,
- result_pool, scratch_pool);
+ svn_node_file, result_pool, scratch_pool);
if (err == SVN_NO_ERROR)
return SVN_NO_ERROR;
if (err->apr_err != SVN_ERR_NODE_UNEXPECTED_KIND)
@@ -1503,106 +1440,9 @@ svn_wc__get_entry(const svn_wc_entry_t *
svn_dirent_local_style(local_abspath,
scratch_pool));
- if (kind == svn_node_unknown)
- {
- /* They wanted a (directory) stub, but this isn't a directory. */
- if (need_parent_stub && (*entry)->kind != svn_node_dir)
- return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
- _("'%s' is not of the right kind"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
-
- /* The actual (directory) information was wanted, but we got a stub. */
- if (!need_parent_stub
- && (*entry)->kind == svn_node_dir
- && *(*entry)->name != '\0')
- return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
- _("'%s' is not of the right kind"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__get_entry_versioned(const svn_wc_entry_t **entry,
- svn_wc_context_t *wc_ctx,
- const char *local_abspath,
- svn_node_kind_t kind,
- svn_boolean_t show_hidden,
- svn_boolean_t need_parent_stub,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_error_t *err;
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
- /* We call this with allow_unversioned=TRUE, since the error returned is
- different than our callers currently expect. We catch the NULL entry
- below and return the correct error. */
- err = svn_wc__get_entry(entry, wc_ctx->db, local_abspath, TRUE, kind,
- need_parent_stub, result_pool, scratch_pool);
- if (err && (err->apr_err == SVN_ERR_WC_MISSING
- || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND
- || err->apr_err == SVN_ERR_NODE_UNEXPECTED_KIND))
- {
- svn_error_clear(err);
- *entry = NULL;
- }
- else if (err)
- return svn_error_return(err);
-
-
- if (*entry && !show_hidden)
- {
- svn_boolean_t hidden;
-
- SVN_ERR(svn_wc__entry_is_hidden(&hidden, *entry));
- if (hidden)
- *entry = NULL;
- }
-
- if (! *entry)
- return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
- _("'%s' is not under version control"),
- svn_dirent_local_style(local_abspath,
- scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_wc__node_is_deleted(svn_boolean_t *deleted,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
-{
- const svn_wc_entry_t *entry;
- svn_error_t *err;
-
- /* ### rewrite this in terms of wc_db. */
-
- err = svn_wc__get_entry(&entry, db, local_abspath, FALSE,
- svn_node_unknown, TRUE, scratch_pool, scratch_pool);
- if (err)
- {
- if (err->apr_err != SVN_ERR_NODE_UNEXPECTED_KIND)
- return svn_error_return(err);
-
- /* We asked for the parent stub, but got a file. No big deal. We have
- what we wanted for a file. */
- svn_error_clear(err);
- }
-
- *deleted = entry->deleted;
return SVN_NO_ERROR;
}
-
/* TODO ### Rewrite doc string to mention ENTRIES_ALL; not ADM_ACCESS.
Prune the deleted entries from the cached entries in ADM_ACCESS, and
@@ -1692,7 +1532,8 @@ svn_wc_entries_read(apr_hash_t **entries
}
-/* */
+/* No transaction required: called from write_entry which is itself
+ transaction-wrapped. */
static svn_error_t *
insert_base_node(svn_sqlite__db_t *sdb,
const db_base_node_t *base_node,
@@ -1700,6 +1541,10 @@ insert_base_node(svn_sqlite__db_t *sdb,
{
svn_sqlite__stmt_t *stmt;
+#ifndef SVN_WC__NODES_ONLY
+ /* ### NODE_DATA when switching to NODE_DATA, replace the
+ query below with STMT_INSERT_BASE_NODE_DATA_FOR_ENTRY_1
+ and adjust the parameters bound. Can't do that yet. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_INSERT_BASE_NODE_FOR_ENTRY));
@@ -1728,13 +1573,8 @@ insert_base_node(svn_sqlite__db_t *sdb,
SVN_ERR(svn_sqlite__bind_int64(stmt, 7, base_node->revision));
- /* ### in per-subdir operation, if we're about to write a directory and
- ### it is *not* "this dir", then we're writing a row in the parent
- ### directory about the child. note that in the kind. */
/* ### kind might be "symlink" or "unknown" */
- if (base_node->kind == svn_node_dir && *base_node->local_relpath != '\0')
- SVN_ERR(svn_sqlite__bind_text(stmt, 8, "subdir"));
- else if (base_node->kind == svn_node_none)
+ if (base_node->kind == svn_node_none)
SVN_ERR(svn_sqlite__bind_text(stmt, 5, "unknown"));
else
SVN_ERR(svn_sqlite__bind_text(stmt, 8,
@@ -1764,7 +1604,69 @@ insert_base_node(svn_sqlite__db_t *sdb,
scratch_pool));
/* Execute and reset the insert clause. */
- return svn_error_return(svn_sqlite__insert(NULL, stmt));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+#endif
+#ifdef SVN_WC__NODES
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_INSERT_BASE_NODE_FOR_ENTRY_1));
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "issisr",
+ base_node->wc_id,
+ base_node->local_relpath,
+ base_node->parent_relpath,
+ base_node->repos_id,
+ base_node->repos_relpath,
+ base_node->revision));
+
+ if (base_node->presence == svn_wc__db_status_not_present)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 7, "not-present"));
+ else if (base_node->presence == svn_wc__db_status_normal)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 7, "normal"));
+ else if (base_node->presence == svn_wc__db_status_absent)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 7, "absent"));
+ else if (base_node->presence == svn_wc__db_status_incomplete)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 7, "incomplete"));
+ else if (base_node->presence == svn_wc__db_status_excluded)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 7, "excluded"));
+
+ /* ### kind might be "symlink" or "unknown" */
+ if (base_node->kind == svn_node_none)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8, "unknown"));
+ else
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8,
+ svn_node_kind_to_word(base_node->kind)));
+
+ if (base_node->checksum)
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 9, base_node->checksum,
+ scratch_pool));
+
+ /* ### strictly speaking, changed_rev should be valid for present nodes. */
+ if (SVN_IS_VALID_REVNUM(base_node->changed_rev))
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 10, base_node->changed_rev));
+ if (base_node->changed_date)
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 11, base_node->changed_date));
+ if (base_node->changed_author)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 12, base_node->changed_author));
+
+ SVN_ERR(svn_sqlite__bind_text(stmt, 13, svn_depth_to_word(base_node->depth)));
+
+ if (base_node->properties)
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 14, base_node->properties,
+ scratch_pool));
+
+ if (base_node->translated_size != SVN_INVALID_FILESIZE)
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 15, base_node->translated_size));
+
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 16, base_node->last_mod_time));
+
+ /* Execute and reset the insert clause. */
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+
+#endif
+ return SVN_NO_ERROR;
}
/* */
@@ -1775,6 +1677,9 @@ insert_working_node(svn_sqlite__db_t *sd
{
svn_sqlite__stmt_t *stmt;
+ /* ### NODE_DATA when switching to NODE_DATA, replace the
+ query below with STMT_INSERT_WORKING_NODE_DATA_2
+ and adjust the parameters bound. Can't do that yet. */
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_WORKING_NODE));
SVN_ERR(svn_sqlite__bind_int64(stmt, 1, working_node->wc_id));
@@ -1793,13 +1698,7 @@ insert_working_node(svn_sqlite__db_t *sd
else if (working_node->presence == svn_wc__db_status_excluded)
SVN_ERR(svn_sqlite__bind_text(stmt, 4, "excluded"));
- /* ### in per-subdir operation, if we're about to write a directory and
- ### it is *not* "this dir", then we're writing a row in the parent
- ### directory about the child. note that in the kind. */
- if (working_node->kind == svn_node_dir
- && *working_node->local_relpath != '\0')
- SVN_ERR(svn_sqlite__bind_text(stmt, 5, "subdir"));
- else if (working_node->kind == svn_node_none)
+ if (working_node->kind == svn_node_none)
SVN_ERR(svn_sqlite__bind_text(stmt, 5, "unknown"));
else
SVN_ERR(svn_sqlite__bind_text(stmt, 5,
@@ -1848,7 +1747,72 @@ insert_working_node(svn_sqlite__db_t *sd
/* ### we should bind 'symlink_target' (20) as appropriate. */
/* Execute and reset the insert clause. */
- return svn_error_return(svn_sqlite__insert(NULL, stmt));
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+#ifdef SVN_WC__NODE_DATA
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_INSERT_WORKING_NODE_DATA_1));
+
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 1, working_node->wc_id));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 2, working_node->local_relpath));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 3,
+ (*working_node->local_relpath == '\0') ? 1 : 2));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 4, working_node->parent_relpath));
+
+ /* ### need rest of values */
+ if (working_node->presence == svn_wc__db_status_normal)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 5, "normal"));
+ else if (working_node->presence == svn_wc__db_status_not_present)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 5, "not-present"));
+ else if (working_node->presence == svn_wc__db_status_base_deleted)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 5, "base-deleted"));
+ else if (working_node->presence == svn_wc__db_status_incomplete)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 5, "incomplete"));
+ else if (working_node->presence == svn_wc__db_status_excluded)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 5, "excluded"));
+
+ if (working_node->kind == svn_node_none)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 6, "unknown"));
+ else
+ SVN_ERR(svn_sqlite__bind_text(stmt, 6,
+ svn_node_kind_to_word(working_node->kind)));
+
+ if (working_node->copyfrom_repos_path)
+ {
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 7,
+ working_node->copyfrom_repos_id));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8,
+ working_node->copyfrom_repos_path));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 9, working_node->copyfrom_revnum));
+ }
+
+ if (working_node->checksum)
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 10, working_node->checksum,
+ scratch_pool));
+
+ if (SVN_IS_VALID_REVNUM(working_node->changed_rev))
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 11, working_node->changed_rev));
+ if (working_node->changed_date)
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 12, working_node->changed_date));
+ if (working_node->changed_author)
+ SVN_ERR(svn_sqlite__bind_text(stmt, 13, working_node->changed_author));
+
+ SVN_ERR(svn_sqlite__bind_text(stmt, 14,
+ svn_depth_to_word(working_node->depth)));
+
+ if (working_node->properties)
+ SVN_ERR(svn_sqlite__bind_properties(stmt, 15, working_node->properties,
+ scratch_pool));
+
+ /* ### we should bind 'symlink_target' (16) as appropriate. */
+
+ /* Execute and reset the insert clause. */
+ SVN_ERR(svn_sqlite__insert(NULL, stmt));
+
+#endif
+
+ return SVN_NO_ERROR;
}
/* */
@@ -2110,12 +2074,25 @@ write_entry(svn_wc__db_t *db,
{
base_node->kind = entry->kind;
- if (entry->incomplete)
+ /* All subdirs are initially incomplete, they stop being
+ incomplete when the entries file in the subdir is
+ upgraded and remain incomplete if that doesn't happen. */
+ if (entry->kind == svn_node_dir
+ && strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR))
{
- /* ### nobody should have set the presence. */
- SVN_ERR_ASSERT(base_node->presence == svn_wc__db_status_normal);
base_node->presence = svn_wc__db_status_incomplete;
}
+ else
+ {
+
+ if (entry->incomplete)
+ {
+ /* ### nobody should have set the presence. */
+ SVN_ERR_ASSERT(base_node->presence
+ == svn_wc__db_status_normal);
+ base_node->presence = svn_wc__db_status_incomplete;
+ }
+ }
}
if (entry->kind == svn_node_dir)
@@ -2231,7 +2208,15 @@ write_entry(svn_wc__db_t *db,
svn_checksum_md5,
entry->checksum, scratch_pool));
- if (entry->schedule == svn_wc_schedule_delete)
+ /* All subdirs start of incomplete, and stop being incomplete
+ when the entries file in the subdir is upgraded. */
+ if (entry->kind == svn_node_dir
+ && strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR))
+ {
+ working_node->presence = svn_wc__db_status_incomplete;
+ working_node->kind = svn_node_dir;
+ }
+ else if (entry->schedule == svn_wc_schedule_delete)
{
if (entry->incomplete)
{
@@ -2305,7 +2290,8 @@ struct entries_write_baton
svn_wc__db_t *db;
apr_int64_t repos_id;
apr_int64_t wc_id;
- const char *local_abspath;
+ const char *dir_abspath;
+ const char *new_root_abspath;
apr_hash_t *entries;
};
@@ -2318,11 +2304,12 @@ entries_write_new_cb(void *baton,
{
struct entries_write_baton *ewb = baton;
svn_wc__db_t *db = ewb->db;
- const char *local_abspath = ewb->local_abspath;
+ const char *dir_abspath = ewb->dir_abspath;
+ const char *new_root_abspath = ewb->new_root_abspath;
const svn_wc_entry_t *this_dir;
apr_hash_index_t *hi;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- const char *repos_root;
+ const char *repos_root, *old_root_abspath, *dir_relpath;
/* Get a copy of the "this dir" entry for comparison purposes. */
this_dir = apr_hash_get(ewb->entries, SVN_WC_ENTRY_THIS_DIR,
@@ -2332,13 +2319,24 @@ entries_write_new_cb(void *baton,
if (! this_dir)
return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
_("No default entry in directory '%s'"),
- svn_dirent_local_style(local_abspath,
+ svn_dirent_local_style(dir_abspath,
iterpool));
repos_root = this_dir->repos;
+ old_root_abspath = svn_dirent_get_longest_ancestor(dir_abspath,
+ new_root_abspath,
+ scratch_pool);
+
+ SVN_ERR_ASSERT(old_root_abspath[0]);
+
+ dir_relpath = svn_dirent_skip_ancestor(old_root_abspath, dir_abspath);
+
/* Write out "this dir" */
SVN_ERR(write_entry(db, sdb, ewb->wc_id, ewb->repos_id, repos_root,
- this_dir, SVN_WC_ENTRY_THIS_DIR, local_abspath,
+ this_dir,
+ dir_relpath,
+ svn_dirent_join(new_root_abspath, dir_relpath,
+ scratch_pool),
this_dir, FALSE, FALSE, iterpool));
for (hi = apr_hash_first(scratch_pool, ewb->entries); hi;
@@ -2346,7 +2344,7 @@ entries_write_new_cb(void *baton,
{
const char *name = svn__apr_hash_index_key(hi);
const svn_wc_entry_t *this_entry = svn__apr_hash_index_val(hi);
- const char *child_abspath;
+ const char *child_abspath, *child_relpath;
svn_pool_clear(iterpool);
@@ -2356,9 +2354,14 @@ entries_write_new_cb(void *baton,
/* Write the entry. Pass TRUE for create locks, because we still
use this function for upgrading old working copies. */
- child_abspath = svn_dirent_join(local_abspath, name, iterpool);
+ child_abspath = svn_dirent_join(dir_abspath, name, iterpool);
+ child_relpath = svn_dirent_skip_ancestor(old_root_abspath, child_abspath);
SVN_ERR(write_entry(db, sdb, ewb->wc_id, ewb->repos_id, repos_root,
- this_entry, name, child_abspath, this_dir,
+ this_entry,
+ child_relpath,
+ svn_dirent_join(new_root_abspath, child_relpath,
+ scratch_pool),
+ this_dir,
FALSE, TRUE,
iterpool));
}
@@ -2373,7 +2376,8 @@ svn_wc__write_upgraded_entries(svn_wc__d
svn_sqlite__db_t *sdb,
apr_int64_t repos_id,
apr_int64_t wc_id,
- const char *local_abspath,
+ const char *dir_abspath,
+ const char *new_root_abspath,
apr_hash_t *entries,
apr_pool_t *scratch_pool)
{
@@ -2382,7 +2386,8 @@ svn_wc__write_upgraded_entries(svn_wc__d
ewb.db = db;
ewb.repos_id = repos_id;
ewb.wc_id = wc_id;
- ewb.local_abspath = local_abspath;
+ ewb.dir_abspath = dir_abspath;
+ ewb.new_root_abspath = new_root_abspath;
ewb.entries = entries;
/* Run this operation in a transaction to speed up SQLite.
@@ -2392,630 +2397,6 @@ svn_wc__write_upgraded_entries(svn_wc__d
scratch_pool));
}
-struct write_one_entry_baton
-{
- svn_wc__db_t *db;
- const char *local_abspath;
- const svn_wc_entry_t *this_dir;
- const svn_wc_entry_t *this_entry;
-};
-
-/* Rewrites a single entry inside a sqlite transaction
- Implements svn_sqlite__transaction_callback_t. */
-static svn_error_t *
-write_one_entry_cb(void *baton,
- svn_sqlite__db_t *sdb,
- apr_pool_t *scratch_pool)
-{
- struct write_one_entry_baton *woeb = baton;
- svn_wc__db_t *db = woeb->db;
- const char *local_abspath = woeb->local_abspath;
- const svn_wc_entry_t *this_dir = woeb->this_dir;
- const svn_wc_entry_t *this_entry = woeb->this_entry;
- const char *this_abspath = svn_dirent_join(local_abspath, this_entry->name,
- scratch_pool);
- const void *base_props = NULL;
- const void *working_props = NULL;
- const void *actual_props = NULL;
- apr_size_t base_prop_len;
- apr_size_t working_prop_len;
- apr_size_t actual_prop_len;
- apr_hash_t *dav_cache;
- const svn_checksum_t *base_checksum;
- svn_sqlite__stmt_t *stmt;
- const char *repos_root;
- apr_int64_t repos_id;
- apr_int64_t wc_id;
- svn_error_t *err;
- svn_boolean_t got_row;
-
- SVN_ERR_ASSERT(this_dir && this_entry);
-
- /* Get the repos ID. */
- if (this_dir->uuid != NULL)
- {
- /* ### does this need to be done on a per-entry basis instead of
- ### the per-directory way we do it now? me thinks yes...
- ###
- ### when do we harvest repository entries which no longer have
- ### any members? */
- SVN_ERR(svn_wc__db_repos_ensure(&repos_id, db, local_abspath,
- this_dir->repos, this_dir->uuid,
- scratch_pool));
- repos_root = this_dir->repos;
- }
- else
- {
- repos_id = 0;
- repos_root = NULL;
- }
-
- SVN_ERR(fetch_wc_id(&wc_id, sdb));
-
- /* Before we nuke all the nodes, we need to get a few values */
-
- /* The dav cache is not in STMT_SELECT_BASE_NODE */
- err = svn_wc__db_base_get_dav_cache(&dav_cache, db, this_abspath,
- scratch_pool, scratch_pool);
- if (err)
- {
- if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_return(err);
- svn_error_clear(err); /* No BASE record */
- dav_cache = NULL;
- }
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_BASE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
- SVN_ERR(svn_sqlite__step(&got_row, stmt));
- if (got_row)
- {
- base_props = svn_sqlite__column_blob(stmt, 13, &base_prop_len,
- scratch_pool);
-
- err = svn_sqlite__column_checksum(&base_checksum, stmt, 5, scratch_pool);
- /* ### SVN_EXPERIMENTAL_PRISTINE:
- base_checksum is originally MD-5 but will later be SHA-1. The
- base_checksum is not yet handled by this function. */
-
- SVN_ERR(svn_error_compose_create(err, svn_sqlite__reset(stmt)));
- }
- else
- SVN_ERR(svn_sqlite__reset(stmt));
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
- SVN_ERR(svn_sqlite__step(&got_row, stmt));
- if (got_row)
- {
- /* No need to store the working checksum, that is stored in the entry */
- working_props = svn_sqlite__column_blob(stmt, 15, &working_prop_len,
- scratch_pool);
- }
- SVN_ERR(svn_sqlite__reset(stmt));
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_ACTUAL_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
- SVN_ERR(svn_sqlite__step(&got_row, stmt));
- if (got_row)
- {
- actual_props = svn_sqlite__column_blob(stmt, 6, &actual_prop_len,
- scratch_pool);
- }
- SVN_ERR(svn_sqlite__reset(stmt));
-
- /* Remove the WORKING, BASE and ACTUAL nodes for this entry */
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
- SVN_ERR(svn_sqlite__step_done(stmt));
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_BASE_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
- SVN_ERR(svn_sqlite__step_done(stmt));
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_DELETE_ACTUAL_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, this_entry->name));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
- SVN_ERR(write_entry(db, sdb, wc_id, repos_id, repos_root, this_entry,
- this_entry->name, this_abspath, this_dir,
- actual_props != NULL, FALSE, scratch_pool));
-
- if (dav_cache)
- SVN_ERR(svn_wc__db_base_set_dav_cache(db, this_abspath, dav_cache,
- scratch_pool));
-
- if (base_props)
- {
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_BASE_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "isb", wc_id, this_entry->name,
- base_props, base_prop_len));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
-
- if (working_props)
- {
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_WORKING_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "isb", wc_id, this_entry->name,
- working_props, working_prop_len));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
-
- if (actual_props)
- {
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_UPDATE_ACTUAL_PROPS));
- SVN_ERR(svn_sqlite__bindf(stmt, "isb", wc_id, this_entry->name,
- actual_props, actual_prop_len));
- SVN_ERR(svn_sqlite__step_done(stmt));
- }
-
- /* TODO: Update base checksum if needed */
- return SVN_NO_ERROR;
-}
-
-/* */
-static svn_error_t *
-write_one_entry(svn_wc__db_t *db,
- const char *local_abspath,
- const svn_wc_entry_t *this_dir,
- const svn_wc_entry_t *this_entry,
- apr_pool_t *scratch_pool)
-{
- struct write_one_entry_baton woeb;
- svn_sqlite__db_t *sdb;
-
- /* ### need the SDB so we can jam rows directly into it. */
- SVN_ERR(svn_wc__db_temp_borrow_sdb(&sdb, db, local_abspath,
- svn_wc__db_openmode_readwrite,
- scratch_pool));
- woeb.db = db;
- woeb.local_abspath = local_abspath;
- woeb.this_dir = this_dir;
- woeb.this_entry = this_entry;
-
- /* Run this operation in a transaction to speed up SQLite.
- See http://www.sqlite.org/faq.html#q19 for more details */
- return svn_error_return(
- svn_sqlite__with_transaction(sdb, write_one_entry_cb, &woeb,
- scratch_pool));
-}
-
-
-
-/* Update the entry CUR_ENTRY, according to the combination of
- entry data found in ENTRY and masked by MODIFY_FLAGS.
- The requested changes will be folded (merged) into
- the entry's existing state.
- Also cleanups meaningless fields combinations.
-
- PARENT_ENTRY must be passed, in order to grab certain "default" values.
-
- POOL will be used to allocate memory referenced by ENTRIES.
- */
-static svn_error_t *
-fold_entry(svn_wc_entry_t *cur_entry,
- const char *name,
- int modify_flags,
- const svn_wc_entry_t *entry,
- const svn_wc_entry_t *parent_entry,
- apr_pool_t *pool)
-{
- SVN_ERR_ASSERT(cur_entry != NULL);
- SVN_ERR_ASSERT(name != NULL);
- SVN_ERR_ASSERT(entry != NULL);
-
- /* Name (just a safeguard here, really) */
- if (! cur_entry->name)
- cur_entry->name = apr_pstrdup(pool, name);
-
- /* Revision */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_REVISION)
- cur_entry->revision = entry->revision;
-
- /* Ancestral URL in repository */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_URL)
- cur_entry->url = entry->url ? apr_pstrdup(pool, entry->url) : NULL;
-
- /* Kind */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_KIND)
- cur_entry->kind = entry->kind;
-
- /* Schedule: handled by caller. */
-
- /* Checksum */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_CHECKSUM)
- cur_entry->checksum = entry->checksum
- ? apr_pstrdup(pool, entry->checksum)
- : NULL;
-
- /* Copy-related stuff */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_COPIED)
- cur_entry->copied = entry->copied;
-
- if (modify_flags & SVN_WC__ENTRY_MODIFY_COPYFROM_URL)
- cur_entry->copyfrom_url = entry->copyfrom_url
- ? apr_pstrdup(pool, entry->copyfrom_url)
- : NULL;
-
- if (modify_flags & SVN_WC__ENTRY_MODIFY_COPYFROM_REV)
- cur_entry->copyfrom_rev = entry->copyfrom_rev;
-
- /* Deleted state */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_DELETED)
- cur_entry->deleted = entry->deleted;
-
- /* Absent state is no longer passed to entry_modify() */
-
- /* text_time, prop_time no longer passed to entry_modify() */
-
- /* Conflict stuff no longer passed to entry_modify() */
-
- /* Last-commit flags are no longer passed to entry_modify() */
-
- /* LOCK flags are no longer passed to entry_modify(). */
-
- /* changelist is no longer modified with this function. */
-
- /* has-props, prop-mods, cachable-props, and present-props are deprecated,
- so we do not copy them. */
-
- /* keep_local is no longer modified with this function */
-
- /* Note that we don't bother to fold entry->depth, because it is
- only meaningful on the this-dir entry anyway. */
-
- /* tree_conflict_data is never modified via entry_t. */
-
- /* Absorb defaults from the parent dir, if any, unless this is a
- subdir entry. */
- if (cur_entry->kind != svn_node_dir && parent_entry != NULL)
- {
- if ((cur_entry->revision == SVN_INVALID_REVNUM)
- && (cur_entry->kind != svn_node_dir))
- cur_entry->revision = parent_entry->revision;
- }
-
- /* Cleanup meaningless fields */
-
- /* ### svn_wc_schedule_delete is the minimal value. We need it because it's
- impossible to NULLify copyfrom_url with log-instructions.
-
- Note that I tried to find the smallest collection not to clear these
- fields for, but this condition still fails the test suite:
-
- !(entry->schedule == svn_wc_schedule_add
- || entry->schedule == svn_wc_schedule_replace
- || (entry->schedule == svn_wc_schedule_normal && entry->copied)))
-
- */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE
- && cur_entry->schedule == svn_wc_schedule_delete)
- {
- cur_entry->copied = FALSE;
- cur_entry->copyfrom_rev = SVN_INVALID_REVNUM;
- cur_entry->copyfrom_url = NULL;
- }
-
- /* working_size is no longer passed to entry_modify() */
-
- /* keep_local makes sense only when we are going to delete directory. */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE
- && cur_entry->schedule != svn_wc_schedule_delete)
- {
- cur_entry->keep_local = FALSE;
- }
-
- /* File externals are no longer passed to entry_modify(). */
-
- return SVN_NO_ERROR;
-}
-
-
-/* Our general purpose intelligence module for handling a scheduling change
- to a single entry.
-
- Given an ENTRY with name NAME, examine the caller's requested scheduling
- change and the current state of the entry and its directory entry
- THIS_DIR_ENTRY, which can be equal to ENTRY.
-
- Determine the final schedule for the entry based on NEW_SCHEDULE and the
- entries.
-
- The output can be:
- * *SKIP_SCHEDULE_CHANGE set to true, when no schedule change is necessary.
- * Or a schedule change.
-
- In all these cases *RESULT_SCHEDULE contains the new schedule value.
- */
-static svn_error_t *
-fold_scheduling(svn_boolean_t *skip_schedule_change,
- svn_wc_schedule_t *result_schedule,
- const svn_wc_entry_t *this_dir_entry,
- const svn_wc_entry_t *entry,
- svn_wc_schedule_t new_schedule,
- const char *name)
-{
- SVN_ERR_ASSERT(this_dir_entry);
- SVN_ERR_ASSERT(new_schedule != svn_wc_schedule_replace);
-
- *skip_schedule_change = FALSE;
- *result_schedule = new_schedule;
-
- /* The only operation valid on an item not already in revision
- control is addition. */
- if (entry == NULL)
- {
- if (new_schedule == svn_wc_schedule_add)
- return SVN_NO_ERROR;
-
- return svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
- _("'%s' is not under version control"),
- name);
- }
-
- /* At this point, we know the following things:
-
- 1. There is already an entry for this item in the entries file
- whose existence is either _normal or _added (or about to
- become such), which for our purposes mean the same thing.
-
- 2. We have been asked to merge in a state change, not to
- explicitly set the state. */
-
- /* Here are some cases that are parent-directory sensitive.
- Basically, we make sure that we are not allowing versioned
- resources to just sorta dangle below directories marked for
- deletion. */
- if ((entry != this_dir_entry)
- && (this_dir_entry->schedule == svn_wc_schedule_delete))
- {
- if (new_schedule == svn_wc_schedule_add)
- return
- svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
- _("Can't add '%s' to deleted directory; "
- "try undeleting its parent directory first"),
- name);
- }
-
- if (entry->absent && (new_schedule == svn_wc_schedule_add))
- {
- return svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
- _("'%s' is marked as absent, so it cannot "
- "be scheduled for addition"),
- name);
- }
-
- if (entry->schedule == svn_wc_schedule_normal
- && new_schedule == svn_wc_schedule_add
- && !entry->deleted)
- {
- /* You can't add something that's already been added to
- revision control... unless it's got a 'deleted' state */
- return svn_error_createf(SVN_ERR_WC_SCHEDULE_CONFLICT, NULL,
- _("Entry '%s' is already under version "
- "control"),
- name);
- }
-
- if (entry->schedule == svn_wc_schedule_normal)
- {
- if (new_schedule == svn_wc_schedule_normal)
- {
- /* No-op case. */
- *skip_schedule_change = TRUE;
- }
- }
- else if (entry->schedule == svn_wc_schedule_add)
- {
- if (new_schedule == svn_wc_schedule_normal
- || new_schedule == svn_wc_schedule_add)
- {
- /* These are both no-op cases. Normal is obvious, as is add.
-
- ### Neither case is obvious: above, we throw an error if
- ### already versioned, so why not here too?
- */
- *skip_schedule_change = TRUE;
- }
- else if (new_schedule == svn_wc_schedule_delete)
- {
- /* This is deleting a node added over the top of a not-present
- (DELETED=true) node. Return it to the not-present state. */
- /* ### not trying to delete the directory, and this is a
- ### not-present node. (otherwise, caller handles this case) */
- SVN_ERR_ASSERT(entry != this_dir_entry);
- SVN_ERR_ASSERT(entry->deleted);
-
- *result_schedule = svn_wc_schedule_normal;
- }
- }
- else if (entry->schedule == svn_wc_schedule_delete)
- {
- if (new_schedule == svn_wc_schedule_normal)
- {
- /* Reverting a delete results in normal */
- }
- else if (new_schedule == svn_wc_schedule_delete)
- {
- /* This is a no-op case */
- *skip_schedule_change = TRUE;
- }
- else if (new_schedule == svn_wc_schedule_add)
- {
- /* Re-adding an entry marked for deletion? This is really a
- replace operation. */
- *result_schedule = svn_wc_schedule_replace;
- }
- }
- else
- {
- /* Only possible state left. */
- SVN_ERR_ASSERT(entry->schedule == svn_wc_schedule_replace);
-
- if (new_schedule == svn_wc_schedule_normal)
- {
- /* Reverting replacements results in normal */
- }
- else if (new_schedule == svn_wc_schedule_add)
- {
- /* Adding a to-be-replaced entry breaks down to ((delete +
- add) + add) which might deserve a warning, but we'll just
- no-op it. */
- *skip_schedule_change = TRUE;
- }
- else if (new_schedule == svn_wc_schedule_delete)
- {
- /* Deleting a to-be-replaced entry breaks down to ((delete +
- add) + delete) which resolves to a flat deletion. */
- *result_schedule = svn_wc_schedule_delete;
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-
-
-static svn_error_t *
-entry_modify(svn_wc__db_t *db,
- const char *local_abspath,
- svn_node_kind_t kind,
- svn_boolean_t parent_stub,
- const svn_wc_entry_t *entry_mods,
- int modify_flags,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *subpool = svn_pool_create(scratch_pool);
- svn_error_t *err;
- svn_wc_adm_access_t *adm_access;
- const char *adm_abspath;
- const char *name;
- const svn_wc_entry_t *parent_entry;
- svn_wc_entry_t *cur_entry;
- svn_wc_schedule_t new_schedule;
-
- SVN_ERR_ASSERT(entry_mods);
-
- SVN_ERR(get_entry_access_info(&adm_abspath, &name, db, local_abspath,
- kind, parent_stub, subpool, subpool));
-
- /* Load ADM_ABSPATH's whole entries file:
- Is there an existing access baton for this path? */
- adm_access = svn_wc__adm_retrieve_internal2(db, adm_abspath, subpool);
- if (adm_access != NULL)
- {
- /* Are we allowed to write to this admin area? */
- SVN_ERR(svn_wc__write_check(db, svn_wc__adm_access_abspath(adm_access),
- subpool));
-
- /* Zap any cached entries. We're about to change them. */
- svn_wc__adm_access_set_entries(adm_access, NULL);
- }
- /* ### else: should we have some kind of write check here? */
-
- /* Cast our non-const CUR_ENTRY appropriately. It will be allocated for
- us in SUB_POOL, so we actually know it is modifiable. */
- SVN_ERR(read_entry_pair(&parent_entry, (const svn_wc_entry_t **)&cur_entry,
- db, adm_abspath, name, subpool, subpool));
-
- if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE)
- {
- new_schedule = entry_mods->schedule;
-
- /* We may just want to force the scheduling change in. Otherwise,
- call our special function to fold the change in. */
- if (!(modify_flags & SVN_WC__ENTRY_MODIFY_FORCE))
- {
- svn_boolean_t skip_schedule_change;
-
- /* ### adm_ops.c is the only code that attempts to transition to
- ### schedule_replace, but it uses FORCE. */
- SVN_ERR_ASSERT(entry_mods->schedule != svn_wc_schedule_replace);
-
- /* If we are deleting a node that has been added, then simply
- remove the entry. Do NOT do this for an add over a not-present
- BASE node (the DELETED flag). */
- if (entry_mods->schedule == svn_wc_schedule_delete
- && cur_entry != NULL
- && cur_entry->schedule == svn_wc_schedule_add
- && !cur_entry->deleted)
- {
- SVN_ERR(svn_wc__db_temp_op_remove_entry(db, local_abspath,
- subpool));
- svn_pool_destroy(subpool);
- return SVN_NO_ERROR;
- }
-
- /* If scheduling changes were made, we have a special routine to
- manage those modifications. */
- SVN_ERR(fold_scheduling(&skip_schedule_change,
- &new_schedule,
- parent_entry,
- cur_entry,
- entry_mods->schedule,
- name));
-
- if (skip_schedule_change)
- modify_flags &= ~SVN_WC__ENTRY_MODIFY_SCHEDULE;
- }
- }
-
- /* Yay! Our "modify" function can actually "create". Bleah. */
- if (cur_entry == NULL)
- cur_entry = alloc_entry(subpool);
-
- /* Fold in the changes, and write them out. */
- if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE)
- cur_entry->schedule = new_schedule;
- SVN_ERR(fold_entry(cur_entry, name, modify_flags, entry_mods, parent_entry,
- subpool));
-
- err = write_one_entry(db, adm_abspath,
- parent_entry,
- cur_entry,
- subpool);
-
- svn_pool_destroy(subpool); /* Close wc.db handles */
-
- return svn_error_return(err);
-}
-
-
-svn_error_t *
-svn_wc__entry_modify(svn_wc__db_t *db,
- const char *local_abspath,
- svn_node_kind_t kind,
- const svn_wc_entry_t *entry,
- int modify_flags,
- apr_pool_t *scratch_pool)
-{
- return svn_error_return(entry_modify(db, local_abspath, kind, FALSE,
- entry, modify_flags, scratch_pool));
-}
-
-
-svn_error_t *
-svn_wc__entry_modify_stub(svn_wc__db_t *db,
- const char *local_abspath,
- const svn_wc_entry_t *entry,
- int modify_flags,
- apr_pool_t *scratch_pool)
-{
- SVN_ERR_ASSERT((modify_flags & ~(
- /* from adm_ops.c */
- SVN_WC__ENTRY_MODIFY_SCHEDULE
- | SVN_WC__ENTRY_MODIFY_KIND
- | SVN_WC__ENTRY_MODIFY_REVISION
- | SVN_WC__ENTRY_MODIFY_COPYFROM_URL
- | SVN_WC__ENTRY_MODIFY_COPYFROM_REV
- | SVN_WC__ENTRY_MODIFY_COPIED
- | SVN_WC__ENTRY_MODIFY_CHECKSUM
- )) == 0);
- return svn_error_return(entry_modify(db, local_abspath,
- svn_node_dir, TRUE,
- entry, modify_flags, scratch_pool));
-}
-
svn_wc_entry_t *
svn_wc_entry_dup(const svn_wc_entry_t *entry, apr_pool_t *pool)
@@ -3282,7 +2663,7 @@ svn_wc_walk_entries3(const char *path,
}
SVN_ERR(svn_wc__get_entry(&entry, db, local_abspath, FALSE,
- svn_node_file, FALSE, pool, pool));
+ svn_node_file, pool, pool));
err = walk_callbacks->found_entry(path, entry, walk_baton, pool);
if (err)
@@ -3302,52 +2683,3 @@ svn_wc_walk_entries3(const char *path,
svn_dirent_local_style(local_abspath, pool)),
walk_baton, pool);
}
-
-svn_error_t *
-svn_wc__temp_mark_missing_not_present(const char *local_abspath,
- svn_wc_context_t *wc_ctx,
- apr_pool_t *scratch_pool)
-{
- svn_wc__db_status_t status;
- svn_wc__db_kind_t kind;
- const char *repos_relpath, *repos_root_url, *repos_uuid;
- svn_revnum_t revision;
-
- SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
- SVN_ERR(svn_wc__db_read_info(&status, &kind, &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,
- wc_ctx->db, local_abspath,
- scratch_pool, scratch_pool));
- if (kind == svn_wc__db_kind_dir
- && status == svn_wc__db_status_obstructed_delete)
- {
- if (!repos_relpath)
- SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
- &repos_uuid,
- wc_ctx->db, local_abspath,
- scratch_pool, scratch_pool));
-
- SVN_ERR(svn_wc__db_temp_op_remove_entry(wc_ctx->db, local_abspath,
- scratch_pool));
-
- if (!SVN_IS_VALID_REVNUM(revision))
- revision = 0; /* Just make one up */
-
- SVN_ERR(svn_wc__db_base_add_absent_node(wc_ctx->db, local_abspath,
- repos_relpath, repos_root_url,
- repos_uuid, revision,
- svn_wc__db_kind_dir,
- svn_wc__db_status_not_present,
- NULL, NULL, scratch_pool));
-
- return SVN_NO_ERROR;
- }
-
- return svn_error_createf(SVN_ERR_WC_PATH_FOUND, NULL,
- _("Unexpectedly found '%s': "
- "path is marked 'missing'"),
- svn_dirent_local_style(local_abspath, scratch_pool));
-}
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/entries.h Wed Sep 15 19:32:26 2010
@@ -37,66 +37,6 @@
extern "C" {
#endif /* __cplusplus */
-/* The MODIFY_FLAGS that tell svn_wc__entry_modify which parameters to
- pay attention to. ### These should track the changes made to the
- SVN_WC__ENTRY_ATTR_* #defines! */
-#define SVN_WC__ENTRY_MODIFY_REVISION 0x00000001
-#define SVN_WC__ENTRY_MODIFY_URL 0x00000002
-#define SVN_WC__ENTRY_MODIFY_KIND 0x00000004
-/* ### gap */
-#define SVN_WC__ENTRY_MODIFY_CHECKSUM 0x00000010
-#define SVN_WC__ENTRY_MODIFY_SCHEDULE 0x00000020
-#define SVN_WC__ENTRY_MODIFY_COPIED 0x00000040
-#define SVN_WC__ENTRY_MODIFY_DELETED 0x00000080
-#define SVN_WC__ENTRY_MODIFY_COPYFROM_URL 0x00000100
-#define SVN_WC__ENTRY_MODIFY_COPYFROM_REV 0x00000200
-/* ### gap */
-
-/* ...ORed together with this to mean: just set the schedule to the new
- value, instead of treating the new value as a change of state to be
- merged with the current schedule. */
-#define SVN_WC__ENTRY_MODIFY_FORCE 0x00020000
-
-
-/* Modify the entry for LOCAL_ABSPATH in DB by folding in
- ("merging") changes, and sync those changes to disk. New values
- for the entry are pulled from their respective fields in ENTRY, and
- MODIFY_FLAGS is a bitmask to specify which of those fields to pay
- attention to, formed from the values SVN_WC__ENTRY_MODIFY_....
-
- ### Old doc: "ADM_ACCESS must hold a write lock."
-
- If LOCAL_ABSPATH specifies a directory, its full entry will be modified.
- To modify its "parent stub" entry, use svn_wc__entry_modify_stub().
-
- "Folding in" a change means, in most cases, simply replacing the field
- with the new value. However, for the "schedule" field, unless
- MODIFY_FLAGS includes SVN_WC__ENTRY_MODIFY_FORCE (in which case just take
- the new schedule from ENTRY), it means to determine the schedule that the
- entry should end up with if the "schedule" value from ENTRY represents a
- change/add/delete/replace being made to the
- ### base / working / base and working version(s) ?
- of the node.
-
- Perform all allocations in SCRATCH_POOL.
-*/
-svn_error_t *
-svn_wc__entry_modify(svn_wc__db_t *db,
- const char *local_abspath,
- svn_node_kind_t kind,
- const svn_wc_entry_t *entry,
- int modify_flags,
- apr_pool_t *scratch_pool);
-
-
-/* Like svn_wc__entry_modify(), but modifies the "parent stub". */
-svn_error_t *
-svn_wc__entry_modify_stub(svn_wc__db_t *db,
- const char *local_abspath,
- const svn_wc_entry_t *entry,
- int modify_flags,
- apr_pool_t *scratch_pool);
-
/** Get an ENTRY for the given LOCAL_ABSPATH.
*
* This API does not require an access baton, just a wc_db handle (DB).
@@ -112,19 +52,9 @@ svn_wc__entry_modify_stub(svn_wc__db_t *
* If you specify FILE/DIR, and the entry is *something else*, then
* SVN_ERR_NODE_UNEXPECTED_KIND will be returned.
*
- * For directory nodes, sometimes the caller may want the "stub" from the
- * parent directory. This is usually to examine the DELETED flag. When
- * this is desired, pass TRUE for NEED_PARENT_STUB. It is illegal to pass
- * TRUE if KIND == FILE.
- *
* If KIND == UNKNOWN, and you request the parent stub, and the node turns
* out to NOT be a directory, then SVN_ERR_NODE_UNEXPECTED_KIND is returned.
*
- * If KIND == UNKNOWN, and you request the actual file/dir data (by setting
- * NEED_PARENT_STUB to FALSE), and the node turns out to be a DIR (as
- * specified by the parent), but the subdirectory is NOT present (obstructed
- * or missing), then SVN_ERR_NODE_UNEXPECTED_KIND is returned.
- *
* NOTE: if SVN_ERR_NODE_UNEXPECTED_KIND is returned, then the ENTRY *IS*
* valid and may be examined. For any other error, ENTRY *IS NOT* valid.
*
@@ -141,11 +71,9 @@ svn_wc__get_entry(const svn_wc_entry_t *
const char *local_abspath,
svn_boolean_t allow_unversioned,
svn_node_kind_t kind,
- svn_boolean_t need_parent_stub,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
-
/* Is ENTRY in a 'hidden' state in the sense of the 'show_hidden'
* switches on svn_wc_entries_read(), svn_wc_walk_entries*(), etc.? */
svn_error_t *
@@ -166,18 +94,10 @@ svn_wc__write_upgraded_entries(svn_wc__d
apr_int64_t repos_id,
apr_int64_t wc_id,
const char *dir_abspath,
+ const char *new_root_abspath,
apr_hash_t *entries,
apr_pool_t *scratch_pool);
-
-/* ### return a flag corresponding to the classic "DELETED" concept. */
-svn_error_t *
-svn_wc__node_is_deleted(svn_boolean_t *deleted,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
-
-
/* Parse a file external specification in the NULL terminated STR and
place the path in PATH_RESULT, the peg revision in PEG_REV_RESULT
and revision number in REV_RESULT. STR may be NULL, in which case
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.c Wed Sep 15 19:32:26 2010
@@ -35,8 +35,6 @@
#include "adm_files.h"
#include "lock.h"
#include "props.h"
-#include "log.h"
-#include "entries.h"
#include "wc_db.h"
#include "svn_private_config.h"
@@ -110,6 +108,7 @@ svn_error_t *
svn_wc__internal_check_wc(int *wc_format,
svn_wc__db_t *db,
const char *local_abspath,
+ svn_boolean_t check_path,
apr_pool_t *scratch_pool)
{
svn_error_t *err;
@@ -144,6 +143,64 @@ svn_wc__internal_check_wc(int *wc_format
}
}
+ if (*wc_format >= SVN_WC__WC_NG_VERSION)
+ {
+ svn_wc__db_status_t db_status;
+ svn_wc__db_kind_t db_kind;
+
+ if (check_path)
+ {
+ /* If a node is not a directory, it is not a working copy
+ directory. This allows creating new working copies as
+ a path below an existing working copy. */
+ svn_node_kind_t wc_kind;
+
+ SVN_ERR(svn_io_check_path(local_abspath, &wc_kind, scratch_pool));
+ if (wc_kind != svn_node_dir)
+ {
+ *wc_format = 0; /* Not a directory, so not a wc-directory */
+ return SVN_NO_ERROR;
+ }
+ }
+
+ err = svn_wc__db_read_info(&db_status, &db_kind, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, local_abspath,
+ scratch_pool, scratch_pool);
+
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ *wc_format = 0;
+ return SVN_NO_ERROR;
+ }
+ else
+ SVN_ERR(err);
+
+ if (db_kind != svn_wc__db_kind_dir)
+ {
+ /* The WC thinks there must be a file, so this is not
+ a wc-directory */
+ *wc_format = 0;
+ return SVN_NO_ERROR;
+ }
+
+ switch (db_status)
+ {
+ case svn_wc__db_status_not_present:
+ case svn_wc__db_status_absent:
+ case svn_wc__db_status_excluded:
+ /* If there is a directory here, it is not related to the parent
+ working copy: Obstruction */
+ *wc_format = 0;
+ return SVN_NO_ERROR;
+ default:
+ break;
+ }
+ }
+
return SVN_NO_ERROR;
}
@@ -152,10 +209,13 @@ svn_error_t *
svn_wc_check_wc2(int *wc_format,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
+ /* ### Should we pass TRUE for check_path to find obstructions and
+ missing directories? */
return svn_error_return(
- svn_wc__internal_check_wc(wc_format, wc_ctx->db, local_abspath, pool));
+ svn_wc__internal_check_wc(wc_format, wc_ctx->db, local_abspath, FALSE,
+ scratch_pool));
}
@@ -205,7 +265,7 @@ pool_cleanup_locked(void *p)
{
/* There is no remaining work, so we're good to remove any
potential "physical" lock. */
- err = svn_wc__db_wclock_remove(db, lock->abspath, scratch_pool);
+ err = svn_wc__db_wclock_release(db, lock->abspath, scratch_pool);
}
}
svn_error_clear(err);
@@ -310,8 +370,22 @@ adm_access_alloc(svn_wc_adm_access_t **a
if (write_lock)
{
- SVN_ERR(svn_wc__db_wclock_set(db, lock->abspath, 0, scratch_pool));
- SVN_ERR(svn_wc__db_temp_mark_locked(db, lock->abspath, scratch_pool));
+ svn_boolean_t owns_lock;
+
+ /* If the db already owns a lock, we can't add an extra lock record */
+ SVN_ERR(svn_wc__db_wclock_owns_lock(&owns_lock, db, path, FALSE,
+ scratch_pool));
+
+ /* If DB owns the lock, but when there is no access baton open for this
+ directory, old access baton based code is trying to access data that
+ was previously locked by new code. Just hand them the lock, or
+ important code paths like svn_wc_add3() will start failing */
+ if (!owns_lock
+ || svn_wc__adm_retrieve_internal2(db, lock->abspath, scratch_pool))
+ {
+ SVN_ERR(svn_wc__db_wclock_obtain(db, lock->abspath, 0, FALSE,
+ scratch_pool));
+ }
}
err = add_to_shared(lock, scratch_pool);
@@ -319,7 +393,7 @@ adm_access_alloc(svn_wc_adm_access_t **a
if (err)
return svn_error_compose_create(
err,
- svn_wc__db_wclock_remove(db, lock->abspath, scratch_pool));
+ svn_wc__db_wclock_release(db, lock->abspath, scratch_pool));
/* ### does this utf8 thing really/still apply?? */
/* It's important that the cleanup handler is registered *after* at least
@@ -409,7 +483,8 @@ probe(svn_wc__db_t *db,
const char *local_abspath;
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
- SVN_ERR(svn_wc__internal_check_wc(&wc_format, db, local_abspath, pool));
+ SVN_ERR(svn_wc__internal_check_wc(&wc_format, db, local_abspath,
+ FALSE, pool));
}
/* a "version" of 0 means a non-wc directory */
@@ -456,7 +531,8 @@ open_single(svn_wc_adm_access_t **adm_ac
svn_wc_adm_access_t *lock;
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
- err = svn_wc__internal_check_wc(&wc_format, db, local_abspath, scratch_pool);
+ err = svn_wc__internal_check_wc(&wc_format, db, local_abspath, FALSE,
+ scratch_pool);
if (wc_format == 0 || (err && APR_STATUS_IS_ENOENT(err->apr_err)))
{
return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, err,
@@ -503,8 +579,9 @@ close_single(svn_wc_adm_access_t *adm_ac
return SVN_NO_ERROR;
/* Physically unlock if required */
- SVN_ERR(svn_wc__db_temp_own_lock(&locked, adm_access->db,
- adm_access->abspath, scratch_pool));
+ SVN_ERR(svn_wc__db_wclock_owns_lock(&locked, adm_access->db,
+ adm_access->abspath, TRUE,
+ scratch_pool));
if (locked)
{
if (!preserve_lock)
@@ -515,9 +592,9 @@ close_single(svn_wc_adm_access_t *adm_ac
from the working copy. It is an error for the lock to
have disappeared if the administrative area still exists. */
- svn_error_t *err = svn_wc__db_wclock_remove(adm_access->db,
- adm_access->abspath,
- scratch_pool);
+ svn_error_t *err = svn_wc__db_wclock_release(adm_access->db,
+ adm_access->abspath,
+ scratch_pool);
if (err)
{
if (svn_wc__adm_area_exists(adm_access->abspath, scratch_pool))
@@ -549,38 +626,38 @@ close_single(svn_wc_adm_access_t *adm_ac
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_wc__adm_available(svn_boolean_t *available,
- svn_wc__db_kind_t *kind,
- svn_boolean_t *obstructed,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
+/* Retrieves the KIND of LOCAL_ABSPATH and whether its administrative data is
+ available in the working copy.
+
+ *AVAILABLE is set to TRUE when the node and its metadata are available,
+ otherwise to FALSE (due to obstruction, missing, absence, exclusion,
+ or a "not-present" child).
+
+ KIND can be NULL.
+
+ ### note: this function should go away when we move to a single
+ ### adminstrative area. */
+static svn_error_t *
+adm_available(svn_boolean_t *available,
+ svn_wc__db_kind_t *kind,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ apr_pool_t *scratch_pool)
{
svn_wc__db_status_t status;
- svn_depth_t depth;
if (kind)
*kind = svn_wc__db_kind_unknown;
SVN_ERR(svn_wc__db_read_info(&status, kind, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, &depth, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL,
db, local_abspath, scratch_pool, scratch_pool));
- if (obstructed)
- *obstructed = (status == svn_wc__db_status_obstructed ||
- status == svn_wc__db_status_obstructed_add ||
- status == svn_wc__db_status_obstructed_delete);
-
- *available = !(status == svn_wc__db_status_obstructed ||
- status == svn_wc__db_status_obstructed_add ||
- status == svn_wc__db_status_obstructed_delete ||
- status == svn_wc__db_status_absent ||
- status == svn_wc__db_status_excluded ||
- status == svn_wc__db_status_not_present ||
- depth == svn_depth_exclude);
+ *available = !(status == svn_wc__db_status_absent
+ || status == svn_wc__db_status_excluded
+ || status == svn_wc__db_status_not_present);
return SVN_NO_ERROR;
}
@@ -629,7 +706,7 @@ do_open(svn_wc_adm_access_t **adm_access
{
const char *node_abspath;
svn_wc__db_kind_t kind;
- svn_boolean_t available, obstructed;
+ svn_boolean_t available;
const char *name = APR_ARRAY_IDX(children, i, const char *);
svn_pool_clear(iterpool);
@@ -640,12 +717,11 @@ do_open(svn_wc_adm_access_t **adm_access
node_abspath = svn_dirent_join(local_abspath, name, iterpool);
- SVN_ERR(svn_wc__adm_available(&available,
- &kind,
- &obstructed,
- db,
- node_abspath,
- scratch_pool));
+ SVN_ERR(adm_available(&available,
+ &kind,
+ db,
+ node_abspath,
+ scratch_pool));
if (kind != svn_wc__db_kind_dir)
continue;
@@ -662,12 +738,6 @@ do_open(svn_wc_adm_access_t **adm_access
/* node_access has been registered in DB, so we don't need
to do anything with it. */
}
- else if (obstructed)
- {
- svn_wc__db_temp_set_access(lock->db, node_abspath,
- (svn_wc_adm_access_t *)&missing,
- iterpool);
- }
}
}
svn_pool_destroy(iterpool);
@@ -1038,43 +1108,15 @@ child_is_disjoint(svn_boolean_t *disjoin
const char *node_repos_root, *node_repos_relpath, *node_repos_uuid;
const char *parent_repos_root, *parent_repos_relpath, *parent_repos_uuid;
svn_wc__db_status_t parent_status;
- const apr_array_header_t *children;
const char *parent_abspath, *base;
- svn_error_t *err;
- svn_boolean_t found_in_parent = FALSE;
- int i;
-
- svn_dirent_split(local_abspath, &parent_abspath, &base, scratch_pool);
/* Check if the parent directory knows about this node */
- err = svn_wc__db_read_children(&children, db, parent_abspath, scratch_pool,
- scratch_pool);
-
- if (err && err->apr_err == SVN_ERR_WC_NOT_DIRECTORY)
- {
- svn_error_clear(err);
- *disjoint = TRUE;
- return SVN_NO_ERROR;
- }
- else
- SVN_ERR(err);
+ SVN_ERR(svn_wc__db_is_wcroot(disjoint, db, local_abspath, scratch_pool));
- for (i = 0; i < children->nelts; i++)
- {
- const char *name = APR_ARRAY_IDX(children, i, const char *);
+ if (*disjoint)
+ return SVN_NO_ERROR;
- if (strcmp(name, base) == 0)
- {
- found_in_parent = TRUE;
- break;
- }
- }
-
- if (!found_in_parent)
- {
- *disjoint = TRUE;
- return SVN_NO_ERROR;
- }
+ svn_dirent_split(&parent_abspath, &base, local_abspath, scratch_pool);
SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, &node_repos_relpath,
&node_repos_root, &node_repos_uuid, NULL, NULL,
@@ -1083,8 +1125,8 @@ child_is_disjoint(svn_boolean_t *disjoin
db, local_abspath,
scratch_pool, scratch_pool));
- /* If the node does not have its own relpath, its value is inherited
- which tells us that it is not disjoint. */
+ /* If the node does not have its own repos_relpath, its value is inherited
+ from a parent node, which implies that the node is not disjoint. */
if (node_repos_relpath == NULL)
{
*disjoint = FALSE;
@@ -1283,11 +1325,10 @@ open_anchor(svn_wc_adm_access_t **anchor
if (! t_access)
{
- svn_boolean_t available, obstructed;
+ svn_boolean_t available;
svn_wc__db_kind_t kind;
- err = svn_wc__adm_available(&available, &kind, &obstructed,
- db, local_abspath, pool);
+ err = adm_available(&available, &kind, db, local_abspath, pool);
if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
svn_error_clear(err);
@@ -1296,13 +1337,6 @@ open_anchor(svn_wc_adm_access_t **anchor
svn_error_clear(svn_wc_adm_close2(p_access, pool));
return svn_error_return(err);
}
- if (obstructed && kind == svn_wc__db_kind_dir)
- {
- /* Child PATH is missing. */
- svn_wc__db_temp_set_access(db, local_abspath,
- (svn_wc_adm_access_t *)&missing,
- pool);
- }
}
*anchor_access = p_access ? p_access : t_access;
@@ -1406,9 +1440,9 @@ svn_wc_adm_locked(const svn_wc_adm_acces
{
svn_boolean_t locked;
apr_pool_t *subpool = svn_pool_create(adm_access->pool);
- svn_error_t *err = svn_wc__db_temp_own_lock(&locked, adm_access->db,
- adm_access->abspath,
- subpool);
+ svn_error_t *err = svn_wc__db_wclock_owns_lock(&locked, adm_access->db,
+ adm_access->abspath, TRUE,
+ subpool);
svn_pool_destroy(subpool);
if (err)
@@ -1428,7 +1462,8 @@ svn_wc__write_check(svn_wc__db_t *db,
{
svn_boolean_t locked;
- SVN_ERR(svn_wc__db_temp_own_lock(&locked, db, local_abspath, scratch_pool));
+ SVN_ERR(svn_wc__db_wclock_owns_lock(&locked, db, local_abspath, FALSE,
+ scratch_pool));
if (!locked)
return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL,
_("No write-lock in '%s'"),
@@ -1448,8 +1483,8 @@ svn_wc_locked2(svn_boolean_t *locked_her
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
if (locked_here != NULL)
- SVN_ERR(svn_wc__db_temp_own_lock(locked_here, wc_ctx->db, local_abspath,
- scratch_pool));
+ SVN_ERR(svn_wc__db_wclock_owns_lock(locked_here, wc_ctx->db, local_abspath,
+ FALSE, scratch_pool));
if (locked != NULL)
SVN_ERR(svn_wc__db_wclocked(locked, wc_ctx->db, local_abspath,
scratch_pool));
@@ -1509,60 +1544,36 @@ svn_wc__adm_get_db(const svn_wc_adm_acce
return adm_access->db;
}
-
-svn_boolean_t
-svn_wc__adm_missing(svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool)
-{
- const svn_wc_adm_access_t *look;
- svn_boolean_t available, obstructed;
- svn_wc__db_kind_t kind;
-
- look = get_from_shared(local_abspath, db, scratch_pool);
-
- if (look != NULL)
- return IS_MISSING(look);
-
- /* When we switch to a single database an access baton can't be
- missing, but until then it can. But if there are no access batons we
- would always return FALSE.
- For this case we check if an access baton could be opened
-
-*/
-
- /* This check must match the check in do_open() */
- svn_error_clear(svn_wc__adm_available(&available, &kind, &obstructed,
- db, local_abspath,
- scratch_pool));
-
- return (kind == svn_wc__db_kind_dir) && !available && obstructed;
-}
-
-
svn_error_t *
-svn_wc__acquire_write_lock(const char **anchor_abspath,
+svn_wc__acquire_write_lock(const char **lock_root_abspath,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
+ svn_boolean_t lock_anchor,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
+ svn_wc__db_t *db = wc_ctx->db;
svn_wc__db_kind_t kind;
- apr_pool_t *iterpool;
- const apr_array_header_t *children;
- int format, i;
svn_error_t *err;
-
- SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
+ SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath,
+ (lock_root_abspath != NULL),
scratch_pool));
- if (anchor_abspath)
+ if (!lock_root_abspath && kind != svn_wc__db_kind_dir)
+ return svn_error_createf(SVN_ERR_WC_NOT_DIRECTORY, NULL,
+ _("Can't obtain lock on non-directory '%s'."),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
+
+ if (lock_anchor)
{
const char *parent_abspath;
svn_wc__db_kind_t parent_kind;
+ SVN_ERR_ASSERT(lock_root_abspath != NULL);
+
parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
- err = svn_wc__db_read_kind(&parent_kind, wc_ctx->db, parent_abspath, TRUE,
+ err = svn_wc__db_read_kind(&parent_kind, db, parent_abspath, TRUE,
scratch_pool);
if (err && SVN_WC__ERR_IS_NOT_CURRENT_WC(err))
{
@@ -1587,67 +1598,31 @@ svn_wc__acquire_write_lock(const char **
_("'%s' is not a working copy"),
svn_dirent_local_style(local_abspath,
scratch_pool));
-
- *anchor_abspath = apr_pstrdup(result_pool, local_abspath);
}
else if (kind != svn_wc__db_kind_dir)
- local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
-
- SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
- scratch_pool, scratch_pool));
-
- /* The current lock paradigm is that each directory holds a lock for itself,
- and there are no inherited locks. In the eventual wc-ng paradigm, a
- lock on a directory, would imply a infinite-depth lock on the children.
- But since we aren't quite there yet, we do the infinite locking
- manually (and be sure to release them in svn_wc__release_write_lock(). */
-
- iterpool = svn_pool_create(scratch_pool);
- for (i = 0; i < children->nelts; i ++)
{
- const char *child_relpath = APR_ARRAY_IDX(children, i, const char *);
- const char *child_abspath;
-
- svn_pool_clear(iterpool);
- child_abspath = svn_dirent_join(local_abspath, child_relpath, iterpool);
+ local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
- SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath, FALSE,
- iterpool));
- if (kind == svn_wc__db_kind_dir)
+ /* Can't lock parents that don't exist */
+ if (kind == svn_wc__db_kind_unknown)
{
- err = svn_wc__acquire_write_lock(NULL, wc_ctx, child_abspath, NULL,
- iterpool);
- if (err && err->apr_err == SVN_ERR_WC_LOCKED)
- {
- while(i >= 0)
- {
- svn_error_t *err2;
- svn_pool_clear(iterpool);
- child_relpath = APR_ARRAY_IDX(children, i, const char *);
- child_abspath = svn_dirent_join(local_abspath, child_relpath,
- iterpool);
- err2 = svn_wc__release_write_lock(wc_ctx, child_abspath,
- iterpool);
- if (err2)
- svn_error_compose(err, err2);
- --i;
- }
- return svn_error_return(err);
- }
+ SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE,
+ scratch_pool));
+
+ if (kind != svn_wc__db_kind_dir)
+ return svn_error_createf(
+ SVN_ERR_WC_NOT_DIRECTORY, NULL,
+ _("Can't obtain lock on non-directory '%s'."),
+ svn_dirent_local_style(local_abspath,
+ scratch_pool));
}
}
- /* We don't want to try and lock an unversioned directory that
- obstructs a versioned directory. */
- err = svn_wc__internal_check_wc(&format, wc_ctx->db, local_abspath, iterpool);
- if (!err && format)
- {
- SVN_ERR(svn_wc__db_wclock_set(wc_ctx->db, local_abspath, 0, iterpool));
- SVN_ERR(svn_wc__db_temp_mark_locked(wc_ctx->db, local_abspath, iterpool));
- }
- svn_error_clear(err);
+ if (lock_root_abspath)
+ *lock_root_abspath = apr_pstrdup(result_pool, local_abspath);
- svn_pool_destroy(iterpool);
+ SVN_ERR(svn_wc__db_wclock_obtain(wc_ctx->db, local_abspath, -1, FALSE,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -1658,18 +1633,8 @@ svn_wc__release_write_lock(svn_wc_contex
const char *local_abspath,
apr_pool_t *scratch_pool)
{
- svn_wc__db_kind_t kind;
- apr_pool_t *iterpool;
- const apr_array_header_t *children;
apr_uint64_t id;
svn_skel_t *work_item;
- svn_boolean_t locked_here;
- int i;
-
- SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, local_abspath, TRUE,
- scratch_pool));
- if (kind != svn_wc__db_kind_dir)
- local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
SVN_ERR(svn_wc__db_wq_fetch(&id, &work_item, wc_ctx->db, local_abspath,
scratch_pool, scratch_pool));
@@ -1679,33 +1644,7 @@ svn_wc__release_write_lock(svn_wc_contex
return SVN_NO_ERROR;
}
- /* We need to recursively remove locks (see comment in
- svn_wc__acquire_write_lock(). */
-
- iterpool = svn_pool_create(scratch_pool);
-
- SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
- scratch_pool, iterpool));
- for (i = 0; i < children->nelts; i ++)
- {
- const char *child_relpath = APR_ARRAY_IDX(children, i, const char *);
- const char *child_abspath;
-
- svn_pool_clear(iterpool);
- child_abspath = svn_dirent_join(local_abspath, child_relpath, iterpool);
-
- SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, child_abspath, FALSE,
- iterpool));
- if (kind == svn_wc__db_kind_dir)
- SVN_ERR(svn_wc__release_write_lock(wc_ctx, child_abspath, iterpool));
- }
-
- SVN_ERR(svn_wc__db_temp_own_lock(&locked_here, wc_ctx->db, local_abspath,
- iterpool));
- if (locked_here)
- SVN_ERR(svn_wc__db_wclock_remove(wc_ctx->db, local_abspath, iterpool));
-
- svn_pool_destroy(iterpool);
+ SVN_ERR(svn_wc__db_wclock_release(wc_ctx->db, local_abspath, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1715,14 +1654,16 @@ svn_wc__call_with_write_lock(svn_wc__wit
void *baton,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
+ svn_boolean_t lock_anchor,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_error_t *err1, *err2;
- SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath,
- scratch_pool, scratch_pool));
- err1 = func(baton, result_pool, scratch_pool);
- err2 = svn_wc__release_write_lock(wc_ctx, local_abspath, scratch_pool);
+ const char *lock_root_abspath;
+ SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath, wc_ctx, local_abspath,
+ lock_anchor, scratch_pool, scratch_pool));
+ err1 = svn_error_return(func(baton, result_pool, scratch_pool));
+ err2 = svn_wc__release_write_lock(wc_ctx, lock_root_abspath, scratch_pool);
return svn_error_compose_create(err1, err2);
}
Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/lock.h Wed Sep 15 19:32:26 2010
@@ -49,39 +49,6 @@ void svn_wc__adm_access_set_entries(svn_
be NULL. */
apr_hash_t *svn_wc__adm_access_entries(svn_wc_adm_access_t *adm_access);
-
-/* Returns TRUE if LOCAL_ABSPATH is a working copy directory that is obstructed
- or missing such that an access baton is not available for LOCAL_ABSPATH.
- This means DB must also include the parent of LOCAL_ABSPATH.
-
- This function falls back to using svn_wc__adm_available() if no access batons
- for LOCAL_ABSPATH are stored in DB. */
-svn_boolean_t svn_wc__adm_missing(svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
-
-/* Retrieves the KIND of LOCAL_ABSPATH and whether its administrative data is
- available in the working copy.
-
- *AVAILABLE is set to TRUE when the node and its metadata are available,
- otherwise to FALSE (due to obstruction, missing, absence, exclusion,
- or a "not-present" child).
-
- *OBSTRUCTED is set to TRUE when the node is not available because
- it is obstructed/missing, otherwise to FALSE.
-
- KIND and OBSTRUCTED can be NULL.
-
- ### note: this function should go away when we move to a single
- ### adminstrative area. */
-svn_error_t *
-svn_wc__adm_available(svn_boolean_t *available,
- svn_wc__db_kind_t *kind,
- svn_boolean_t *obstructed,
- svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
-
/* Same as svn_wc__adm_retrieve_internal, but takes a DB and an absolute
directory path. */
svn_wc_adm_access_t *
@@ -91,21 +58,16 @@ svn_wc__adm_retrieve_internal2(svn_wc__d
/* ### this is probably bunk. but I dunna want to trace backwards-compat
### users of svn_wc_check_wc(). probably gonna be rewritten for wc-ng
- ### in any case. */
+ ### in any case.
+
+ If CHECK_PATH is TRUE, a not-existing directory is not a working copy */
svn_error_t *
svn_wc__internal_check_wc(int *wc_format,
svn_wc__db_t *db,
const char *local_abspath,
+ svn_boolean_t check_path,
apr_pool_t *scratch_pool);
-
-/* Ensure LOCAL_ABSPATH is still locked in DB. Returns the error
- * SVN_ERR_WC_NOT_LOCKED if this is not the case.
- */
-svn_error_t *svn_wc__write_check(svn_wc__db_t *db,
- const char *local_abspath,
- apr_pool_t *scratch_pool);
-
/* Return the working copy database associated with this access baton. */
svn_wc__db_t *
svn_wc__adm_get_db(const svn_wc_adm_access_t *adm_access);