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 2011/04/27 01:15:59 UTC

svn commit: r1096947 - /subversion/trunk/subversion/libsvn_client/merge.c

Author: rhuijben
Date: Tue Apr 26 23:15:59 2011
New Revision: 1096947

URL: http://svn.apache.org/viewvc?rev=1096947&view=rev
Log:
Make merge_file_changed and merge_dir_opened use the result of the obstruction
check to decide whether it needs more information on specific scenarios. This
avoids a number of db operations in the scenario where we don't install a
tree conflict.

* subversion/libsvn_client/merge.c
  (merge_file_changed): Use scratch_pool before the real merge. When not
    obstructed and a not deleted versioned file exists, don't look for tc
    details.
  (merge_dir_opened): Use scratch_pool instead of subpool. Avoid unnecessary
    checks when we already know what we have to know.

Modified:
    subversion/trunk/subversion/libsvn_client/merge.c

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1096947&r1=1096946&r2=1096947&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Tue Apr 26 23:15:59 2011
@@ -1326,8 +1326,10 @@ merge_file_changed(svn_wc_notify_state_t
                    apr_pool_t *scratch_pool)
 {
   merge_cmd_baton_t *merge_b = baton;
-  apr_pool_t *subpool = svn_pool_create(merge_b->pool);
+  apr_pool_t *subpool;
   enum svn_wc_merge_outcome_t merge_outcome;
+  svn_node_kind_t wc_kind;
+  svn_boolean_t is_deleted;
 
   SVN_ERR_ASSERT(mine_abspath && svn_dirent_is_absolute(mine_abspath));
   SVN_ERR_ASSERT(!older_abspath || svn_dirent_is_absolute(older_abspath));
@@ -1337,17 +1339,20 @@ merge_file_changed(svn_wc_notify_state_t
   {
     svn_wc_notify_state_t obstr_state;
 
-    SVN_ERR(perform_obstruction_check(&obstr_state, NULL, NULL, NULL, NULL,
-                                      NULL,
+    SVN_ERR(perform_obstruction_check(&obstr_state, NULL, NULL, NULL,
+                                      &is_deleted, &wc_kind,
                                       merge_b, mine_abspath, svn_node_unknown,
                                       scratch_pool));
     if (obstr_state != svn_wc_notify_state_inapplicable)
       {
+        /* ### a future thought:  if the file is under version control,
+         * but the working file is missing, maybe we can 'restore' the
+         * working file from the text-base, and then allow the merge to run? */
+
         if (content_state)
           *content_state = obstr_state;
         if (prop_state && obstr_state == svn_wc_notify_state_missing)
           *prop_state = svn_wc_notify_state_missing;
-        svn_pool_destroy(subpool);
         return SVN_NO_ERROR;
       }
   }
@@ -1355,56 +1360,49 @@ merge_file_changed(svn_wc_notify_state_t
   /* Other easy outs:  if the merge target isn't under version
      control, or is just missing from disk, fogettaboutit.  There's no
      way svn_wc_merge4() can do the merge. */
-  {
-    svn_node_kind_t kind;
-    svn_node_kind_t wc_kind;
-    svn_depth_t parent_depth;
-
-    SVN_ERR(svn_wc_read_kind(&wc_kind, merge_b->ctx->wc_ctx, mine_abspath,
-                             FALSE, subpool));
-    SVN_ERR(svn_io_check_path(mine_abspath, &kind, subpool));
-
-    /* If the file isn't there due to depth restrictions, do not flag
-     * a conflict. Non-inheritable mergeinfo will be recorded, allowing
-     * future merges into non-shallow working copies to merge changes
-     * we missed this time around. */
-    SVN_ERR(svn_wc__node_get_depth(&parent_depth, merge_b->ctx->wc_ctx,
-                                   svn_dirent_dirname(mine_abspath, subpool),
-                                   subpool));
-    if (wc_kind == svn_node_none
-        && parent_depth < svn_depth_files
-        && parent_depth != svn_depth_unknown)
-      {
-        if (content_state)
-          *content_state = svn_wc_notify_state_missing;
-        if (prop_state)
-          *prop_state = svn_wc_notify_state_missing;
-        svn_pool_destroy(subpool);
-        return SVN_NO_ERROR;
-      }
+  if (wc_kind != svn_node_file || is_deleted)
+    {
+      /* Maybe the node is excluded via depth filtering? */
 
-    /* ### a future thought:  if the file is under version control,
-       but the working file is missing, maybe we can 'restore' the
-       working file from the text-base, and then allow the merge to run?  */
+      if (wc_kind == svn_node_none)
+        {
+          svn_depth_t parent_depth;
 
-    if ((wc_kind == svn_node_none) || (kind != svn_node_file))
-      {
-        /* This is use case 4 described in the paper attached to issue
-         * #2282.  See also notes/tree-conflicts/detection.txt
-         */
-        SVN_ERR(tree_conflict(merge_b, mine_abspath, svn_node_file,
-                              svn_wc_conflict_action_edit,
-                              svn_wc_conflict_reason_missing));
-        if (tree_conflicted)
-          *tree_conflicted = TRUE;
-        if (content_state)
-          *content_state = svn_wc_notify_state_missing;
-        if (prop_state)
-          *prop_state = svn_wc_notify_state_missing;
-        svn_pool_destroy(subpool);
-        return SVN_NO_ERROR;
-      }
-  }
+          /* If the file isn't there due to depth restrictions, do not flag
+           * a conflict. Non-inheritable mergeinfo will be recorded, allowing
+           * future merges into non-shallow working copies to merge changes
+           * we missed this time around. */
+          SVN_ERR(svn_wc__node_get_depth(&parent_depth, merge_b->ctx->wc_ctx,
+                                         svn_dirent_dirname(mine_abspath,
+                                                            scratch_pool),
+                                         scratch_pool));
+          if (parent_depth < svn_depth_files
+              && parent_depth != svn_depth_unknown)
+            {
+              if (content_state)
+                *content_state = svn_wc_notify_state_missing;
+              if (prop_state)
+                *prop_state = svn_wc_notify_state_missing;
+              return SVN_NO_ERROR;
+            }
+        }
+
+      /* This is use case 4 described in the paper attached to issue
+       * #2282.  See also notes/tree-conflicts/detection.txt
+       */
+      SVN_ERR(tree_conflict(merge_b, mine_abspath, svn_node_file,
+                            svn_wc_conflict_action_edit,
+                            svn_wc_conflict_reason_missing));
+      if (tree_conflicted)
+        *tree_conflicted = TRUE;
+      if (content_state)
+        *content_state = svn_wc_notify_state_missing;
+      if (prop_state)
+        *prop_state = svn_wc_notify_state_missing;
+      return SVN_NO_ERROR;
+    }
+
+   subpool = svn_pool_create(merge_b->pool);
 
   /* ### TODO: Thwart attempts to merge into a path that has
      ### unresolved conflicts.  This needs to be smart enough to deal
@@ -2308,19 +2306,16 @@ merge_dir_opened(svn_boolean_t *tree_con
                  apr_pool_t *scratch_pool)
 {
   merge_cmd_baton_t *merge_b = baton;
-  apr_pool_t *subpool = svn_pool_create(merge_b->pool);
   svn_depth_t parent_depth;
-  svn_node_kind_t kind;
-  svn_node_kind_t kind_on_disk;
+  svn_node_kind_t wc_kind;
   svn_wc_notify_state_t obstr_state;
   svn_boolean_t is_deleted;
-  svn_error_t *err;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   /* Check for an obstructed or missing node on disk. */
-  SVN_ERR(perform_obstruction_check(&obstr_state, NULL, NULL, NULL, NULL,
-                                    NULL,
+  SVN_ERR(perform_obstruction_check(&obstr_state, NULL, NULL, NULL,
+                                    &is_deleted, &wc_kind,
                                     merge_b, local_abspath, svn_node_unknown,
                                     scratch_pool));
 
@@ -2329,97 +2324,65 @@ merge_dir_opened(svn_boolean_t *tree_con
       if (skip_children)
         *skip_children = TRUE;
       /* But don't skip THIS, to allow a skip notification */
-      svn_pool_destroy(subpool);
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_wc_read_kind(&kind, merge_b->ctx->wc_ctx,
-                           local_abspath, TRUE, subpool));
-  SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, subpool));
-
-  /* If the parent is too shallow to contain this directory,
-   * and the directory is not present on disk, skip it.
-   * Non-inheritable mergeinfo will be recorded, allowing
-   * future merges into non-shallow working copies to merge
-   * changes we missed this time around. */
-  err = svn_wc__node_get_depth(&parent_depth, merge_b->ctx->wc_ctx,
-                               svn_dirent_dirname(local_abspath, scratch_pool),
-                               scratch_pool);
-  if (err)
+  if (wc_kind != svn_node_dir || is_deleted)
     {
-      if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-        {
-          svn_error_clear(err);
-          parent_depth = svn_depth_unknown;
-        }
-      else
+      if (wc_kind == svn_node_none)
         {
-          svn_pool_destroy(subpool);
-          return svn_error_return(err);
+          /* If the parent is too shallow to contain this directory,
+           * and the directory is not present on disk, skip it.
+           * Non-inheritable mergeinfo will be recorded, allowing
+           * future merges into non-shallow working copies to merge
+           * changes we missed this time around. */
+          SVN_ERR(svn_wc__node_get_depth(&parent_depth, merge_b->ctx->wc_ctx,
+                                         svn_dirent_dirname(local_abspath,
+                                                            scratch_pool),
+                                         scratch_pool));
+          if (parent_depth != svn_depth_unknown &&
+              parent_depth < svn_depth_immediates)
+            {
+              if (skip_children)
+                *skip_children = TRUE;
+              return SVN_NO_ERROR;
+            }
         }
-    }
-  if (kind == svn_node_none &&
-      parent_depth != svn_depth_unknown &&
-      parent_depth < svn_depth_immediates)
-    {
-      if (skip_children)
-        *skip_children = TRUE;
-      svn_pool_destroy(subpool);
-      return SVN_NO_ERROR;
-    }
 
-  /* Find out if this path is deleted. */
-  err = svn_wc__node_is_status_deleted(&is_deleted, merge_b->ctx->wc_ctx,
-                                       local_abspath, subpool);
-  if (err)
-    {
-      if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-        {
-          svn_error_clear(err);
-          is_deleted = FALSE;
-        }
-      else
-        {
-          svn_pool_destroy(subpool);
-          return svn_error_return(err);
+      /* Check for tree conflicts, if any. */
+      
+      /* If we're trying to open a file, the reason for the conflict is
+       * 'replaced'. Because the merge is trying to open the directory,
+       * rather than adding it, the directory must have existed in the
+       * history of the target branch and has been replaced with a file. */
+      if (wc_kind == svn_node_file)
+        {
+          SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_dir,
+                                svn_wc_conflict_action_edit,
+                                svn_wc_conflict_reason_replaced));
+          if (tree_conflicted)
+            *tree_conflicted = TRUE;
         }
-    }
-
-  /* Check for tree conflicts, if any. */
-
-  /* If we're trying to open a file, the reason for the conflict is
-   * 'replaced'. Because the merge is trying to open the directory,
-   * rather than adding it, the directory must have existed in the
-   * history of the target branch and has been replaced with a file. */
-  if (kind == svn_node_file)
-    {
-      SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_dir,
-                            svn_wc_conflict_action_edit,
-                            svn_wc_conflict_reason_replaced));
-      if (tree_conflicted)
-        *tree_conflicted = TRUE;
-    }
 
-  /* If we're trying to open a directory that's locally deleted,
-   * or not present because it was deleted in the history of the
-   * target branch, the reason for the conflict is 'deleted'.
-   *
-   * If the DB says something should be here, but there is
-   * nothing on disk, we're probably in a mixed-revision
-   * working copy and the parent has an outdated idea about
-   * the state of its child. Flag a tree conflict in this case
-   * forcing the user to sanity-check the merge result. */
-  else if (is_deleted || kind == svn_node_none ||
-           (kind_on_disk != kind && kind_on_disk == svn_node_none))
-    {
-      SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_dir,
-                            svn_wc_conflict_action_edit,
-                            svn_wc_conflict_reason_deleted));
-      if (tree_conflicted)
-        *tree_conflicted = TRUE;
+      /* If we're trying to open a directory that's locally deleted,
+       * or not present because it was deleted in the history of the
+       * target branch, the reason for the conflict is 'deleted'.
+       *
+       * If the DB says something should be here, but there is
+       * nothing on disk, we're probably in a mixed-revision
+       * working copy and the parent has an outdated idea about
+       * the state of its child. Flag a tree conflict in this case
+       * forcing the user to sanity-check the merge result. */
+      else if (is_deleted || wc_kind == svn_node_none)
+        {
+          SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_dir,
+                                svn_wc_conflict_action_edit,
+                                svn_wc_conflict_reason_deleted));
+          if (tree_conflicted)
+            *tree_conflicted = TRUE;
+        }
     }
 
-  svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }