You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2012/02/01 23:48:40 UTC
svn commit: r1239382 - in /subversion/trunk/subversion:
libsvn_client/commit_util.c tests/cmdline/commit_tests.py
Author: rhuijben
Date: Wed Feb 1 22:48:40 2012
New Revision: 1239382
URL: http://svn.apache.org/viewvc?rev=1239382&view=rev
Log:
Following up on r1227385, move the checks into the commit harvester to allow
retrieving the added state just once. Make sure we handle calculating the right
parent for copies within copies by retrieving the copy-root of the parent
instead of the copy-root of the item itself.
* subversion/libsvn_client/commit_util.c
(harvest_committables): Add danglers argument and fill it with information
for added children that are an explicit target. (If not we filled it via
the parent). Recurse properly
(svn_client__harvest_committables): Make harvest_committables find the
danglers.
(harvest_copy_committables): Update caller.
* subversion/tests/cmdline/commit_tests.py
(commit_in_dir_scheduled_for_addition): Verify the reported parent path in
the error messages. Make sure the tested item is a committable. Extend test
to include a committable deeper inside a parent.
Modified:
subversion/trunk/subversion/libsvn_client/commit_util.c
subversion/trunk/subversion/tests/cmdline/commit_tests.py
Modified: subversion/trunk/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit_util.c?rev=1239382&r1=1239381&r2=1239382&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit_util.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit_util.c Wed Feb 1 22:48:40 2012
@@ -416,6 +416,10 @@ bail_on_tree_conflicted_ancestor(svn_wc_
by recursing deeper into a dir target. (This is used to skip all file
externals that aren't explicit commit targets.)
+ DANGLERS is a hash table mapping const char* absolute paths of a parent
+ that must be committed to a const char * absolute path of a child that
+ needs them.
+
If CANCEL_FUNC is non-null, call it with CANCEL_BATON to see
if the user has cancelled the operation.
@@ -435,6 +439,7 @@ harvest_committables(svn_wc_context_t *w
svn_boolean_t skip_files,
svn_boolean_t skip_dirs,
svn_boolean_t is_explicit_target,
+ apr_hash_t *danglers,
svn_client__check_url_kind_t check_url_func,
void *check_url_baton,
svn_cancel_func_t cancel_func,
@@ -814,6 +819,50 @@ harvest_committables(svn_wc_context_t *w
}
}
+ /* Make sure we check for dangling children on additions */
+ if (state_flags && is_added && is_explicit_target && danglers)
+ {
+ /* If a node is added, it's parent must exist in the repository at the
+ time of committing */
+
+ svn_boolean_t parent_added;
+ const char *parent_abspath = svn_dirent_dirname(local_abspath,
+ scratch_pool);
+
+ SVN_ERR(svn_wc__node_is_added(&parent_added, wc_ctx, parent_abspath,
+ scratch_pool));
+
+ if (parent_added)
+ {
+ /* The op-root of the parent must be part of the commit */
+ const char *copy_root_abspath;
+ svn_boolean_t parent_is_copy;
+
+ /* Copies are always committed recursively as long as the
+ * copy root is in the commit target list.
+ * So for nodes copied along with a parent, the copy root path
+ * is the dangling parent. See issue #4059. */
+ SVN_ERR(svn_wc__node_get_origin(&parent_is_copy, NULL, NULL, NULL,
+ NULL, ©_root_abspath,
+ wc_ctx, parent_abspath,
+ FALSE, scratch_pool, scratch_pool));
+
+ if (parent_is_copy)
+ parent_abspath = copy_root_abspath;
+
+ /* Copy the parent and target into pool; iterpool
+ lasts only for this loop iteration, and we check
+ danglers after the loop is over. */
+ if (!apr_hash_get(danglers, parent_abspath, APR_HASH_KEY_STRING))
+ {
+ apr_hash_set(danglers,
+ apr_pstrdup(result_pool, parent_abspath),
+ APR_HASH_KEY_STRING,
+ apr_pstrdup(result_pool, local_abspath));
+ }
+ }
+ }
+
if (db_kind != svn_node_dir || depth <= svn_depth_empty)
return SVN_NO_ERROR;
@@ -863,6 +912,7 @@ harvest_committables(svn_wc_context_t *w
(depth < svn_depth_files),
(depth < svn_depth_immediates),
FALSE, /* IS_EXPLICIT_TARGET */
+ danglers,
check_url_func, check_url_baton,
cancel_func, cancel_baton,
notify_func, notify_baton,
@@ -1063,10 +1113,8 @@ svn_client__harvest_committables(svn_cli
for (i = 0; i < targets->nelts; ++i)
{
const char *target_abspath;
- svn_boolean_t is_added;
svn_node_kind_t kind;
const char *repos_root_url;
- svn_error_t *err;
svn_pool_clear(iterpool);
@@ -1103,51 +1151,6 @@ svn_client__harvest_committables(svn_cli
target_abspath,
result_pool, iterpool));
- /* Handle an added/replaced node. */
- SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, target_abspath,
- iterpool));
- if (is_added)
- {
- /* This node is added. Is the parent also added? */
- const char *parent_abspath = svn_dirent_dirname(target_abspath,
- iterpool);
- err = svn_wc__node_is_added(&is_added, ctx->wc_ctx, parent_abspath,
- iterpool);
- if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_createf(
- SVN_ERR_WC_CORRUPT, err,
- _("'%s' is scheduled for addition within unversioned parent"),
- svn_dirent_local_style(target_abspath, iterpool));
- SVN_ERR(err);
-
- if (is_added)
- {
- svn_boolean_t is_copy;
- const char *copy_root_abspath;
-
- /* Copies are always committed recursively as long as the
- * copy root is in the commit target list.
- * So for nodes copied along with a parent, the copy root path
- * is the dangling parent. See issue #4059. */
- SVN_ERR(svn_wc__node_get_origin(&is_copy,
- NULL, NULL, NULL, NULL,
- ©_root_abspath,
- ctx->wc_ctx,
- target_abspath,
- FALSE, iterpool, iterpool));
- if (is_copy && strcmp(copy_root_abspath, target_abspath) != 0)
- parent_abspath = copy_root_abspath;
-
- /* Copy the parent and target into pool; iterpool
- lasts only for this loop iteration, and we check
- danglers after the loop is over. */
- apr_hash_set(danglers,
- apr_pstrdup(scratch_pool, parent_abspath),
- APR_HASH_KEY_STRING,
- apr_pstrdup(scratch_pool, target_abspath));
- }
- }
-
/* Handle our TARGET. */
/* Make sure this isn't inside a working copy subtree that is
* marked as tree-conflicted. */
@@ -1164,6 +1167,7 @@ svn_client__harvest_committables(svn_cli
depth, just_locked, changelist_hash,
FALSE, FALSE,
TRUE /* IS_EXPLICIT_TARGET */,
+ danglers,
check_url_func, check_url_baton,
ctx->cancel_func, ctx->cancel_baton,
ctx->notify_func2, ctx->notify_baton2,
@@ -1258,6 +1262,7 @@ harvest_copy_committables(void *baton, v
NULL,
FALSE, FALSE, /* skip files, dirs */
TRUE, /* IS_EXPLICIT_TARGET (don't care) */
+ NULL,
btn->check_url_func,
btn->check_url_baton,
btn->ctx->cancel_func,
Modified: subversion/trunk/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/commit_tests.py?rev=1239382&r1=1239381&r2=1239382&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/commit_tests.py Wed Feb 1 22:48:40 2012
@@ -1136,19 +1136,26 @@ def commit_in_dir_scheduled_for_addition
A_path = os.path.join(wc_dir, 'A')
Z_path = os.path.join(wc_dir, 'Z')
+ Z_abspath = os.path.abspath(Z_path)
mu_path = os.path.join(wc_dir, 'Z', 'mu')
svntest.main.run_svn(None, 'move', A_path, Z_path)
+
+ # Make sure mu is a committable
+ svntest.main.file_write(mu_path, "xxxx")
# Commit a copied thing inside an added-with-history directory,
# expecting a specific error to occur!
svntest.actions.run_and_verify_commit(wc_dir,
None,
None,
- "not known to exist in the repository",
+ "svn: E200009: '" +
+ re.escape(Z_abspath) +
+ "' is not known to exist in the",
mu_path)
Q_path = os.path.join(wc_dir, 'Q')
+ Q_abspath = os.path.abspath(Q_path)
bloo_path = os.path.join(Q_path, 'bloo')
os.mkdir(Q_path)
@@ -1160,9 +1167,24 @@ def commit_in_dir_scheduled_for_addition
svntest.actions.run_and_verify_commit(wc_dir,
None,
None,
- "not known to exist in the repository",
+ "svn: E200009: '" +
+ re.escape(Q_abspath) +
+ "' is not known to exist in the",
bloo_path)
+ R_path = sbox.ospath('Z/B/R')
+ sbox.simple_mkdir('Z/B/R')
+
+ # Commit a d added thing inside an added directory,
+ # expecting a specific error to occur!
+ svntest.actions.run_and_verify_commit(wc_dir,
+ None,
+ None,
+ "svn: E200009: '" +
+ re.escape(Z_abspath) +
+ "' is not known to exist in the.*",
+ R_path)
+
#----------------------------------------------------------------------
# Does this make sense now that deleted files are always removed from the wc?