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, &copy_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,
-                                              &copy_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?