Author: rhuijben
Date: Fri Feb 6 14:46:49 2015
New Revision: 1657846
URL: http://svn.apache.org/r1657846
Log:
Instead of transforming nodes into an copy by changing their op-depth make
a proper copy, to allow the layer bump code to handle further edge cases
like things that are recorded while shadowing.
* subversion/libsvn_wc/wc-queries.sql
(STMT_UPDATE_OP_DEPTH_RECURSIVE): Remove query.
(STMT_COPY_OP_DEPTH_RECURSIVE): New query.
* subversion/libsvn_wc/wc_db.c
(make_copy_txn): Remove two unused arguments and their handling.
Move the flush, conflict and work item code to caller.
(svn_wc__db_op_make_copy_internal): New function, containing some
bits from make_copy_txn() and some from svn_wc__db_op_make_copy(),
running inside a transaction. Allow handling the other valid make-copy
case.
(svn_wc__db_op_make_copy): Call svn_wc__db_op_make_copy_internal to
do several queries inside a transaction.
* subversion/libsvn_wc/wc_db.h
(svn_wc__db_op_make_copy): Extend documentation.
* subversion/libsvn_wc/wc_db_private.h
(svn_wc__db_op_make_copy_internal): New function.
* subversion/libsvn_wc/wc_db_update_move.c
(tc_editor_delete): Use svn_wc__db_op_make_copy_internal() to make
the copy.
Modified:
subversion/trunk/subversion/libsvn_wc/wc-queries.sql
subversion/trunk/subversion/libsvn_wc/wc_db.c
subversion/trunk/subversion/libsvn_wc/wc_db.h
subversion/trunk/subversion/libsvn_wc/wc_db_private.h
subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1657846&r1=1657845&r2=1657846&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Fri Feb 6 14:46:49
2015
@@ -1026,11 +1026,30 @@ WHERE wc_id = ?1
AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
AND op_depth = ?3
--- STMT_UPDATE_OP_DEPTH_RECURSIVE
-UPDATE nodes SET op_depth = ?4, moved_here = NULL
-WHERE wc_id = ?1
- AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
- AND op_depth = ?3
+/* Duplicated SELECT body to avoid creating temporary table */
+-- STMT_COPY_OP_DEPTH_RECURSIVE
+INSERT INTO nodes (
+ wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
+ revision, presence, depth, kind, changed_revision, changed_date,
+ changed_author, checksum, properties, translated_size, last_mod_time,
+ symlink_target, moved_here, moved_to )
+SELECT
+ wc_id, local_relpath, ?4, parent_relpath, repos_id,
+ repos_path, revision, presence, depth, kind, changed_revision,
+ changed_date, changed_author, checksum, properties, translated_size,
+ last_mod_time, symlink_target, NULL, NULL
+FROM nodes
+WHERE wc_id = ?1 AND op_depth = ?3 AND local_relpath = ?2
+UNION ALL
+SELECT
+ wc_id, local_relpath, ?4, parent_relpath, repos_id,
+ repos_path, revision, presence, depth, kind, changed_revision,
+ changed_date, changed_author, checksum, properties, translated_size,
+ last_mod_time, symlink_target, NULL, NULL
+FROM nodes
+WHERE wc_id = ?1 AND op_depth = ?3
+ AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
+ORDER BY local_relpath
-- STMT_DOES_NODE_EXIST
SELECT 1 FROM nodes WHERE wc_id = ?1 AND local_relpath = ?2
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1657846&r1=1657845&r2=1657846&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Feb 6 14:46:49 2015
@@ -14852,8 +14852,6 @@ static svn_error_t *
make_copy_txn(svn_wc__db_wcroot_t *wcroot,
const char *local_relpath,
int op_depth,
- const svn_skel_t *conflicts,
- const svn_skel_t *work_items,
apr_pool_t *scratch_pool)
{
svn_sqlite__stmt_t *stmt;
@@ -14934,21 +14932,68 @@ make_copy_txn(svn_wc__db_wcroot_t *wcroo
copy_relpath = svn_relpath_join(local_relpath, name, iterpool);
- SVN_ERR(make_copy_txn(wcroot, copy_relpath, op_depth, NULL, NULL,
- iterpool));
+ SVN_ERR(make_copy_txn(wcroot, copy_relpath, op_depth, iterpool));
}
- SVN_ERR(flush_entries(wcroot, svn_dirent_join(wcroot->abspath, local_relpath,
- iterpool),
- svn_depth_empty, iterpool));
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_op_make_copy_internal(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const svn_skel_t *conflicts,
+ const svn_skel_t *work_items,
+ apr_pool_t *scratch_pool)
+{
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+ int op_depth = -1;
+
+ /* The update editor is supposed to call this function when there is
+ no working node for LOCAL_ABSPATH. */
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_WORKING_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ if (have_row)
+ op_depth = svn_sqlite__column_int(stmt, 0);
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ if (have_row)
+ {
+ if (op_depth == relpath_depth(local_relpath))
+ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+ _("Modification of '%s' already exists"),
+ path_for_error_message(wcroot,
+ local_relpath,
+ scratch_pool));
+
+ /* We have a working layer, but not one at the op-depth of local-relpath,
+ so we can create a copy by just copying the lower layer */
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_COPY_OP_DEPTH_RECURSIVE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath,
+ op_depth, relpath_depth(local_relpath)));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+ }
+ else
+ {
+ /* We don't allow copies to contain server-excluded nodes;
+ the update editor is going to have to bail out. */
+ SVN_ERR(catch_copy_of_server_excluded(wcroot, local_relpath,
scratch_pool));
+
+ SVN_ERR(make_copy_txn(wcroot, local_relpath,
+ relpath_depth(local_relpath), scratch_pool));
+ }
if (conflicts)
SVN_ERR(svn_wc__db_mark_conflict_internal(wcroot, local_relpath,
- conflicts, iterpool));
+ conflicts, scratch_pool));
- SVN_ERR(add_work_items(wcroot->sdb, work_items, iterpool));
-
- svn_pool_destroy(iterpool);
+ SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool));
return SVN_NO_ERROR;
}
@@ -14963,8 +15008,6 @@ svn_wc__db_op_make_copy(svn_wc__db_t *db
{
svn_wc__db_wcroot_t *wcroot;
const char *local_relpath;
- svn_sqlite__stmt_t *stmt;
- svn_boolean_t have_row;
SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -14972,30 +15015,14 @@ svn_wc__db_op_make_copy(svn_wc__db_t *db
local_abspath, scratch_pool, scratch_pool));
VERIFY_USABLE_WCROOT(wcroot);
- /* The update editor is supposed to call this function when there is
- no working node for LOCAL_ABSPATH. */
- SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
- STMT_SELECT_WORKING_NODE));
- SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
- SVN_ERR(svn_sqlite__step(&have_row, stmt));
- SVN_ERR(svn_sqlite__reset(stmt));
- if (have_row)
- return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
- _("Modification of '%s' already exists"),
- path_for_error_message(wcroot,
- local_relpath,
- scratch_pool));
-
- /* We don't allow copies to contain server-excluded nodes;
- the update editor is going to have to bail out. */
- SVN_ERR(catch_copy_of_server_excluded(wcroot, local_relpath, scratch_pool));
-
SVN_WC__DB_WITH_TXN(
- make_copy_txn(wcroot, local_relpath,
- relpath_depth(local_relpath), conflicts, work_items,
- scratch_pool),
+ svn_wc__db_op_make_copy_internal(wcroot, local_relpath, conflicts,
work_items,
+ scratch_pool),
wcroot);
+ SVN_ERR(flush_entries(wcroot, local_abspath,
+ svn_depth_infinity, scratch_pool));
+
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1657846&r1=1657845&r2=1657846&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Fri Feb 6 14:46:49 2015
@@ -3246,9 +3246,21 @@ svn_wc__db_temp_op_end_directory_update(
apr_pool_t *scratch_pool);
-/* Copy the base tree at LOCAL_ABSPATH into the working tree as copy,
- leaving any subtree additions and copies as-is. This allows the
- base node tree to be removed. */
+/* When local_abspath has no WORKING layer, copy the base tree at
+ LOCAL_ABSPATH into the working tree as copy, leaving any subtree
+ additions and copies as-is. This may introduce multiple layers if
+ the tree is mixed revision.
+
+ When local_abspath has a WORKING node, but is not an op-root, copy
+ all descendants at the same op-depth to the op-depth of local_abspath,
+ thereby turning this node in a copy of what was already there.
+
+ Fails with a SVN_ERR_WC_PATH_UNEXPECTED_STATUS error if LOCAL_RELPATH
+ is already an op-root (as in that case it can't be copied as that
+ would overwrite what is already there).
+
+ After this operation the copied layer (E.g. BASE) can be removed, without
+ the WORKING nodes chaning. Typical usecase: tree conflict handling */
svn_error_t *
svn_wc__db_op_make_copy(svn_wc__db_t *db,
const char *local_abspath,
Modified: subversion/trunk/subversion/libsvn_wc/wc_db_private.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_private.h?rev=1657846&r1=1657845&r2=1657846&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_private.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_private.h Fri Feb 6 14:46:49
2015
@@ -406,6 +406,14 @@ svn_wc__db_op_copy_layer_internal(svn_wc
svn_skel_t *work_items,
apr_pool_t *scratch_pool);
+/* Like svn_wc__db_op_make_copy but with wcroot, local_relpath */
+svn_error_t *
+svn_wc__db_op_make_copy_internal(svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ const svn_skel_t *conflicts,
+ const svn_skel_t *work_items,
+ apr_pool_t *scratch_pool);
+
/* Extract the moved-to information for LOCAL_RELPATH at OP-DEPTH by
examining the lowest working node above OP_DEPTH. The output paths
Modified: subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c?rev=1657846&r1=1657845&r2=1657846&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c Fri Feb 6
14:46:49 2015
@@ -1154,18 +1154,15 @@ tc_editor_delete(node_move_baton_t *nmb,
if (!is_all_deletes)
{
/* No conflict means no NODES rows at the relpath op-depth
- so it's easy to convert the modified tree into a copy. */
+ so it's easy to convert the modified tree into a copy.
- /* ### Similar to svn_wc__db_op_make_copy(), except that this
- function doesn't support copy from working yet.
-
- ### Note that this breaks DB consistency with the repository
- ### until the layer is updated after the operation */
- SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb,
- STMT_UPDATE_OP_DEPTH_RECURSIVE));
- SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath,
- b->dst_op_depth, relpath_depth(relpath)));
- SVN_ERR(svn_sqlite__step_done(stmt));
+ Note the following assumptions for relpath:
+ * it is not shadowed
+ * it is not the/an op-root. (or we can't make us a copy)
+ */
+
+ SVN_ERR(svn_wc__db_op_make_copy_internal(b->wcroot, relpath,
+ NULL, NULL, scratch_pool));
reason = svn_wc_conflict_reason_edited;
}