You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2010/11/05 13:18:25 UTC
svn commit: r1031532 - in /subversion/trunk/subversion:
libsvn_wc/update_editor.c libsvn_wc/wc-queries.sql libsvn_wc/wc_db.c
tests/libsvn_wc/op-depth-test.c
Author: philip
Date: Fri Nov 5 12:18:25 2010
New Revision: 1031532
URL: http://svn.apache.org/viewvc?rev=1031532&view=rev
Log:
When adding a base node under a working node ensure that there is a
suitable working node at the correct op_depth to delete the base node.
* subversion/libsvn_wc/wc-queries.sql
(STMT_SELECT_LOWEST_WORKING_NODE): New.
* subversion/libsvn_wc/wc_db.c
(extend_parent_delete): New.
(insert_base_node, set_new_dir_to_incomplete_txn): Call
extend_parent_delete to add working node.
* subversion/libsvn_wc/update_editor.c
(add_directory): Don't explicitly add a working node to mark as deleted,
explicitly take over a locally added directory.
(close_file): Don't add working node to mark as deleted.
* subversion/tests/libsvn_wc/op-depth-test.c
(wc_update): New helper.
(test_delete_with_update): New test.
(test_funcs): Mark test_delete_with_update as WIMP.
Modified:
subversion/trunk/subversion/libsvn_wc/update_editor.c
subversion/trunk/subversion/libsvn_wc/wc-queries.sql
subversion/trunk/subversion/libsvn_wc/wc_db.c
subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Fri Nov 5 12:18:25 2010
@@ -2452,14 +2452,10 @@ add_directory(const char *path,
SVN_ERR(svn_wc__ensure_directory(db->local_abspath, pool));
- /* If PATH is within a locally deleted tree then make it also
- scheduled for deletion. We should do this at the same time as
- setting the dir incomplete otherwise the db is temporarily
- invalid. */
- if (pb->in_deleted_and_tree_conflicted_subtree)
- {
- SVN_ERR(svn_wc__db_temp_op_delete(eb->db, db->local_abspath, pool));
- }
+ if (!pb->in_deleted_and_tree_conflicted_subtree
+ && status == svn_wc__db_status_added)
+ /* If there is no conflict we take over any added directory */
+ SVN_ERR(svn_wc__db_temp_op_remove_working(eb->db, db->local_abspath, pool));
/* If this add was obstructed by dir scheduled for addition without
history let close_file() handle the notification because there
@@ -4527,14 +4523,6 @@ close_file(void *file_baton,
/* Deal with the WORKING tree, based on updates to the BASE tree. */
- /* An ancestor was locally-deleted. This file is being added within
- that tree. We need to schedule this file for deletion. This
- should happen at the same time as svn_wc__db_base_add_file. */
- if (fb->dir_baton->in_deleted_and_tree_conflicted_subtree && fb->adding_file)
- {
- SVN_ERR(svn_wc__db_temp_op_delete(eb->db, fb->local_abspath, pool));
- }
-
/* If this file was locally-added and is now being added by the update, we
can toss the local-add, turning this into a local-edit. */
if (fb->add_existed && fb->adding_file)
Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Fri Nov 5 12:18:25 2010
@@ -72,6 +72,13 @@ WHERE wc_id = ?1 AND local_relpath = ?2
ORDER BY op_depth DESC
LIMIT 1;
+-- STMT_SELECT_LOWEST_WORKING_NODE
+SELECT op_depth, presence
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > 0
+ORDER BY op_depth
+LIMIT 1;
+
-- STMT_SELECT_ACTUAL_NODE
SELECT prop_reject, changelist, conflict_old, conflict_new,
conflict_working, tree_conflict_data, properties, conflict_data
@@ -473,7 +480,7 @@ VALUES (?1, ?2, 0,
?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16);
-- STMT_INSERT_WORKING_NODE_FROM_BASE
-INSERT INTO nodes (
+INSERT OR REPLACE INTO nodes (
wc_id, local_relpath, op_depth, parent_relpath, presence, kind, checksum,
changed_revision, changed_date, changed_author, depth, symlink_target,
translated_size, last_mod_time, properties)
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Nov 5 12:18:25 2010
@@ -710,6 +710,84 @@ blank_ibb(insert_base_baton_t *pibb)
}
+/* Extend any delete of the parent of LOCAL_RELPATH to LOCAL_RELPATH.
+
+ Given a wc:
+
+ 0 1 2 3 4
+ normal
+ A normal
+ A/B normal normal
+ A/B/C not-pres normal
+ A/B/C/D normal
+
+ That is checkout, delete A/B, copy a replacement A/B, delete copied
+ child A/B/C, add replacement A/B/C, add A/B/C/D.
+
+ Now an update that adds base nodes for A/B/C, A/B/C/D and A/B/C/D/E
+ must extend the A/B deletion:
+
+ 0 1 2 3 4
+ normal
+ A normal
+ A/B normal normal
+ A/B/C normal not-pres normal
+ A/B/C/D normal base-del normal
+ A/B/C/D/E normal base-del
+
+ When adding a base node if the parent has a working node then the
+ parent base is deleted and this must be extended to cover new base
+ node.
+
+ In the example above A/B/C/D and A/B/C/D/E are the nodes that get
+ the extended delete, A/B/C is already deleted.
+ */
+static svn_error_t *
+extend_parent_delete(svn_sqlite__db_t *sdb,
+ apr_int64_t wc_id,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t have_row;
+ svn_sqlite__stmt_t *stmt;
+ apr_int64_t parent_op_depth;
+ const char *parent_relpath = svn_relpath_dirname(local_relpath, scratch_pool);
+
+ SVN_ERR_ASSERT(local_relpath[0]);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_SELECT_LOWEST_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, parent_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ parent_op_depth = svn_sqlite__column_int64(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (have_row)
+ {
+ apr_int64_t op_depth;
+
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ op_depth = svn_sqlite__column_int64(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+ if (!have_row || parent_op_depth < op_depth)
+ {
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_INSERT_WORKING_NODE_FROM_BASE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isit", wc_id,
+ local_relpath, parent_op_depth,
+ presence_map,
+ svn_wc__db_status_base_deleted));
+ SVN_ERR(svn_sqlite__update(NULL, stmt));
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+
/* */
static svn_error_t *
insert_base_node(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
@@ -773,6 +851,10 @@ insert_base_node(void *baton, svn_sqlite
0 /* BASE */,
scratch_pool));
+ if (parent_relpath)
+ SVN_ERR(extend_parent_delete(sdb, pibb->wc_id, pibb->local_relpath,
+ scratch_pool));
+
SVN_ERR(add_work_items(sdb, pibb->work_items, scratch_pool));
return SVN_NO_ERROR;
@@ -9457,14 +9539,6 @@ set_new_dir_to_incomplete_txn(void *bato
SVN_ERR(create_repos_id(&repos_id, dtb->repos_root_url, dtb->repos_uuid,
sdb, scratch_pool));
- /* Delete the base and working node data */
- SVN_ERR(svn_sqlite__get_statement(&stmt, dtb->pdh->wcroot->sdb,
- STMT_DELETE_NODES));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", dtb->pdh->wcroot->wc_id,
- dtb->local_relpath));
- SVN_ERR(svn_sqlite__step_done(stmt));
-
- /* Insert the incomplete base node */
SVN_ERR(svn_sqlite__get_statement(&stmt, dtb->pdh->wcroot->sdb,
STMT_INSERT_NODE));
@@ -9486,6 +9560,10 @@ set_new_dir_to_incomplete_txn(void *bato
SVN_ERR(svn_sqlite__step_done(stmt));
+ if (parent_relpath)
+ SVN_ERR(extend_parent_delete(dtb->pdh->wcroot->sdb, dtb->pdh->wcroot->wc_id,
+ dtb->local_relpath, scratch_pool));
+
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c?rev=1031532&r1=1031531&r2=1031532&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/op-depth-test.c Fri Nov 5 12:18:25 2010
@@ -200,6 +200,21 @@ wc_commit(wc_baton_t *b, const char *pat
NULL, NULL, NULL, NULL, ctx, b->pool);
}
+static svn_error_t *
+wc_update(wc_baton_t *b, const char *path, svn_revnum_t revnum)
+{
+ svn_client_ctx_t *ctx;
+ apr_array_header_t *result_revs;
+ apr_array_header_t *paths = apr_array_make(b->pool, 1,
+ sizeof(const char *));
+ svn_opt_revision_t revision = { svn_opt_revision_number, { revnum } };
+
+ APR_ARRAY_PUSH(paths, const char *) = wc_path(b, path);
+ SVN_ERR(svn_client_create_context(&ctx, b->pool));
+ return svn_client_update3(&result_revs, paths, &revision, svn_depth_infinity,
+ TRUE, FALSE, FALSE, ctx, b->pool);
+}
+
/* Create the Greek tree on disk in the WC, and commit it. */
static svn_error_t *
add_and_commit_greek_tree(wc_baton_t *b)
@@ -956,6 +971,52 @@ test_repo_wc_copies(const svn_test_opts_
return repo_wc_copies(&b);
}
+static svn_error_t *
+test_delete_with_update(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ wc_baton_t b;
+
+ b.pool = pool;
+ SVN_ERR(svn_test__create_repos_and_wc(&b.repos_url, &b.wc_abspath,
+ "delete_with_update", opts, pool));
+ SVN_ERR(svn_wc_context_create(&b.wc_ctx, NULL, pool, pool));
+ SVN_ERR(wc_mkdir(&b, "A"));
+ SVN_ERR(wc_commit(&b, ""));
+ SVN_ERR(wc_mkdir(&b, "A/B"));
+ SVN_ERR(wc_mkdir(&b, "A/B/C"));
+ SVN_ERR(wc_commit(&b, ""));
+ SVN_ERR(wc_update(&b, "", 1));
+
+ SVN_ERR(wc_delete(&b, "A"));
+ SVN_ERR(wc_mkdir(&b, "A"));
+ SVN_ERR(wc_mkdir(&b, "A/B"));
+ {
+ nodes_row_t rows[] = {
+ { 0, "A", "normal", 1, "A"},
+ { 1, "A", "normal", NO_COPY_FROM},
+ { 2, "A/B", "normal", NO_COPY_FROM},
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "A", rows));
+ }
+ SVN_ERR(wc_update(&b, "", 2));
+ {
+ nodes_row_t rows[] = {
+ { 0, "A", "normal", 2, "A"},
+ { 0, "A/B", "normal", 2, "A/B"},
+ { 0, "A/B/C", "normal", 2, "A/B/C"},
+ { 1, "A", "normal", NO_COPY_FROM},
+ { 1, "A/B", "base-deleted", NO_COPY_FROM},
+ { 1, "A/B/C", "base-deleted", NO_COPY_FROM},
+ { 2, "A/B", "normal", NO_COPY_FROM},
+ { 0 }
+ };
+ SVN_ERR(check_db_rows(&b, "A", rows));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* ---------------------------------------------------------------------- */
/* The list of test functions */
@@ -983,5 +1044,8 @@ struct svn_test_descriptor_t test_funcs[
SVN_TEST_OPTS_WIMP(test_repo_wc_copies,
"test_repo_wc_copies",
"needs op_depth"),
+ SVN_TEST_OPTS_WIMP(test_delete_with_update,
+ "test_test_delete_with_update",
+ "needs op_depth"),
SVN_TEST_NULL
};