You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/07/29 16:48:19 UTC
svn commit: r1152245 - in /subversion/trunk/subversion:
libsvn_client/commit.c libsvn_wc/wc_db.c
Author: stsp
Date: Fri Jul 29 14:48:18 2011
New Revision: 1152245
URL: http://svn.apache.org/viewvc?rev=1152245&view=rev
Log:
Update moved-to information on the BASE path of a node which is being moved
out of, or within, an existing moved subtree. Also, make 'svn commit' deal
with the add-half of such moves correctly.
* subversion/libsvn_wc/wc_db.c
(op_delete_txn): If the node was moved-here and we are moving it away,
we always want to update moved-to in BASE, regardless of whether the node
itself was the op-root of the move that moved it here. Prior to this
commit, we only updated moved-to if the node itself was the op-root.
* subversion/libsvn_client/commit.c
(svn_client_commit5): If the delete-half of a move is not in the
commit target list, look up the op-root of the delete and check
if the op-root is among the commit targets. If it is, the delete-half
of the move will be committed along with it, and we can allow the commit.
Modified:
subversion/trunk/subversion/libsvn_client/commit.c
subversion/trunk/subversion/libsvn_wc/wc_db.c
Modified: subversion/trunk/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit.c?rev=1152245&r1=1152244&r2=1152245&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit.c Fri Jul 29 14:48:18 2011
@@ -1379,19 +1379,72 @@ svn_client_commit5(const apr_array_heade
goto cleanup;
if (moved_from_abspath && delete_op_root_abspath &&
- strcmp(moved_from_abspath, delete_op_root_abspath) == 0 &&
- apr_hash_get(committables->by_path, delete_op_root_abspath,
- APR_HASH_KEY_STRING) == NULL)
+ strcmp(moved_from_abspath, delete_op_root_abspath) == 0)
+
{
- cmt_err = svn_error_createf(
- SVN_ERR_ILLEGAL_TARGET, NULL,
- _("Cannot commit '%s' because it was moved from "
- "'%s' which is not part of the commit; both "
- "sides of the move must be committed together"),
- svn_dirent_local_style(item->path, iterpool),
- svn_dirent_local_style(delete_op_root_abspath,
- iterpool));
- goto cleanup;
+ svn_boolean_t found_delete_half =
+ (apr_hash_get(committables->by_path, delete_op_root_abspath,
+ APR_HASH_KEY_STRING) != NULL);
+
+ if (!found_delete_half)
+ {
+ const char *delete_half_parent_abspath;
+
+ /* The delete-half isn't in the commit target list.
+ * However, it might itself be the child of a deleted node,
+ * either because of another move or a deletion.
+ *
+ * For example, consider: mv A/B B; mv B/C C; commit;
+ * C's moved-from A/B/C is a child of the deleted A/B.
+ * A/B/C does not appear in the commit target list, but
+ * A/B does appear.
+ * (Note that moved-from information is always stored
+ * relative to the BASE tree, so we have 'C moved-from
+ * A/B/C', not 'C moved-from B/C'.)
+ *
+ * An example involving a move and a delete would be:
+ * mv A/B C; rm A; commit;
+ * Now C is moved-from A/B which does not appear in the
+ * commit target list, but A does appear.
+ */
+
+ /* Scan upwards for a deletion op-root from the
+ * delete-half's parent directory. */
+ delete_half_parent_abspath =
+ svn_dirent_dirname(delete_op_root_abspath, iterpool);
+ if (strcmp(delete_op_root_abspath,
+ delete_half_parent_abspath) != 0)
+ {
+ const char *parent_delete_op_root_abspath;
+
+ cmt_err = svn_error_trace(
+ svn_wc__node_get_deleted_ancestor(
+ &parent_delete_op_root_abspath,
+ ctx->wc_ctx, delete_half_parent_abspath,
+ iterpool, iterpool));
+ if (cmt_err)
+ goto cleanup;
+
+ if (parent_delete_op_root_abspath)
+ found_delete_half =
+ (apr_hash_get(committables->by_path,
+ parent_delete_op_root_abspath,
+ APR_HASH_KEY_STRING) != NULL);
+ }
+ }
+
+ if (!found_delete_half)
+ {
+ cmt_err = svn_error_createf(
+ SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("Cannot commit '%s' because it was moved from "
+ "'%s' which is not part of the commit; both "
+ "sides of the move must be committed together"),
+ svn_dirent_local_style(item->path, iterpool),
+ svn_dirent_local_style(delete_op_root_abspath,
+ iterpool));
+ goto cleanup;
+ }
}
}
/* ### TODO: check the delete-half, too */
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1152245&r1=1152244&r2=1152245&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Jul 29 14:48:18 2011
@@ -6070,21 +6070,19 @@ op_delete_txn(void *baton,
if (b->moved_to_relpath)
{
const char *moved_from_relpath;
- const char *delete_op_root_relpath;
/* ### call scan_addition_txn() directly? */
if (status == svn_wc__db_status_added)
SVN_ERR(scan_addition(&status, NULL, NULL, NULL,
NULL, NULL, NULL,
- &moved_from_relpath,
- &delete_op_root_relpath,
+ &moved_from_relpath, NULL,
wcroot, local_relpath,
scratch_pool, scratch_pool));
- if (status == svn_wc__db_status_moved_here &&
- strcmp(moved_from_relpath, delete_op_root_relpath) == 0)
+ if (status == svn_wc__db_status_moved_here)
{
- /* The node has already been moved and is being moved again.
+ /* The node has already been moved, possibly along with a parent,
+ * and is being moved again.
* Update the existing moved_to path at the delete-half of
* the prior move. The source of a move is in the BASE tree
* so it remains constant if a node is moved around multiple