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/07/13 18:25:40 UTC

svn commit: r1361289 - /subversion/trunk/subversion/libsvn_wc/update_editor.c

Author: rhuijben
Date: Fri Jul 13 16:25:40 2012
New Revision: 1361289

URL: http://svn.apache.org/viewvc?rev=1361289&view=rev
Log:
Consolidate the code that fills in details about conflicts in the update editor
to simplify code and avoid unneeded database accesses.

* subversion/libsvn_wc/update_editor.c
  (complete_conflict): New function.

  (mark_directory_edited,
   mark_file_edited): Complete conflict before installing.

  (create_tree_conflict): Remove function.

  (check_tree_conflict): Fix typo in comment. Directly create tree conflict.

  (delete_entry): Fetch data for tree conflict. Remove unused variable. Complete
    conflict before installing.

  (add_directory): Store conflict before clearing local variable. Create conflict
    directly and complete conflict before installing.
  (close_directory): Complete conflict via helper.

  (add_file): Store conflict before clearing local variable. Create conflict
    directly and complete conflict before installing.
  (close_file): Complete conflict via helper.

Modified:
    subversion/trunk/subversion/libsvn_wc/update_editor.c

Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1361289&r1=1361288&r2=1361289&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Fri Jul 13 16:25:40 2012
@@ -857,6 +857,56 @@ make_file_baton(struct file_baton **f_p,
   return SVN_NO_ERROR;
 }
 
+/* Complete a conflict skel by describing the update.
+ *
+ * All temporary allocations are be made in SCRATCH_POOL, while allocations
+ * needed for the returned conflict struct are made in RESULT_POOL.
+ */
+static svn_error_t *
+complete_conflict(svn_skel_t *conflict,
+                  const struct dir_baton *pb,
+                  const char *local_abspath,
+                  const char *old_repos_relpath,
+                  svn_revnum_t old_revision,
+                  svn_node_kind_t kind,
+                  apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+  const struct edit_baton *eb = pb->edit_baton;
+  svn_wc_conflict_version_t *src_left_version;
+  svn_boolean_t is_complete;
+
+  if (!conflict)
+    return SVN_NO_ERROR; /* Not conflicted */
+
+  SVN_ERR(svn_wc__conflict_skel_is_complete(&is_complete, conflict));
+
+  if (is_complete)
+    return SVN_NO_ERROR; /* Already competed */
+
+  if (old_repos_relpath)
+    src_left_version = svn_wc_conflict_version_create2(eb->repos_root,
+                                                       eb->repos_uuid,
+                                                       old_repos_relpath,
+                                                       old_revision,
+                                                       kind,
+                                                       result_pool);
+  else
+    src_left_version = NULL;
+
+
+  if (eb->switch_relpath)
+    SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict,
+                                                src_left_version,
+                                                result_pool, scratch_pool));
+  else
+    SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict,
+                                                src_left_version,
+                                                result_pool, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
 /* Called when a directory is really edited, to avoid marking a
    tree conflict on a node for a no-change edit */
 static svn_error_t *
@@ -873,6 +923,11 @@ mark_directory_edited(struct dir_baton *
   if (db->edit_conflict)
     {
       /* We have a (delayed) tree conflict to install */
+
+      SVN_ERR(complete_conflict(db->edit_conflict, db->parent_baton,
+                                db->local_abspath, db->old_repos_relpath,
+                                db->old_revision, svn_node_dir,
+                                db->pool, scratch_pool));
       SVN_ERR(svn_wc__db_op_mark_conflict(db->edit_baton->db,
                                           db->local_abspath,
                                           db->edit_conflict, NULL,
@@ -901,6 +956,12 @@ mark_file_edited(struct file_baton *fb, 
   if (fb->edit_conflict)
     {
       /* We have a (delayed) tree conflict to install */
+
+      SVN_ERR(complete_conflict(fb->edit_conflict, fb->dir_baton,
+                                fb->local_abspath, fb->old_repos_relpath,
+                                fb->old_revision, svn_node_file,
+                                fb->pool, scratch_pool));
+
       SVN_ERR(svn_wc__db_op_mark_conflict(fb->edit_baton->db,
                                           fb->local_abspath,
                                           fb->edit_conflict, NULL,
@@ -1285,136 +1346,9 @@ node_has_local_mods(svn_boolean_t *modif
   return SVN_NO_ERROR;
 }
 
-
 /* Indicates an unset svn_wc_conflict_reason_t. */
 #define SVN_WC_CONFLICT_REASON_NONE (svn_wc_conflict_reason_t)(-1)
 
-/* Create a tree conflict struct.
- *
- * The REASON is stored directly in the tree conflict info.
- *
- * All temporary allocations are be made in SCRATCH_POOL, while allocations
- * needed for the returned conflict struct are made in RESULT_POOL.
- *
- * All other parameters are identical to and described by
- * check_tree_conflict(), with the slight modification that this function
- * relies on the reason passed in REASON instead of actively looking for one. */
-static svn_error_t *
-create_tree_conflict(svn_skel_t **pconflict,
-                     struct edit_baton *eb,
-                     const char *local_abspath,
-                     svn_wc_conflict_reason_t reason,
-                     svn_wc_conflict_action_t action,
-                     apr_pool_t *result_pool, apr_pool_t *scratch_pool)
-{
-  const char *left_repos_relpath;
-  svn_revnum_t left_revision;
-  svn_node_kind_t left_kind;
-  svn_wc_conflict_version_t *src_left_version;
-
-  *pconflict = NULL;
-
-  SVN_ERR_ASSERT(reason != SVN_WC_CONFLICT_REASON_NONE);
-
-  /* Get the source-left information, i.e. the local state of the node
-   * before any changes were made to the working copy, i.e. the state the
-   * node would have if it was reverted. */
-  if (reason == svn_wc_conflict_reason_added ||
-      reason == svn_wc_conflict_reason_moved_here)
-    {
-      /* ###TODO: It would be nice to tell the user at which URL and
-       * ### revision source-left was empty, which could be quite difficult
-       * ### to code, and is a slight theoretical leap of the svn mind.
-       * ### Update should show
-       * ###   URL: svn_wc__db_scan_addition( &repos_relpath )
-       * ###   REV: The base revision of the parent of before this update
-       * ###        started
-       * ###        ### BUT what if parent was updated/switched away with
-       * ###        ### depth=empty after this node was added?
-       * ### Switch should show
-       * ###   URL: scan_addition URL of before this switch started
-       * ###   REV: same as above */
-
-      /* In case of a local addition, source-left is non-existent / empty. */
-      left_kind = svn_node_none;
-      left_revision = SVN_INVALID_REVNUM;
-      left_repos_relpath = NULL;
-    }
-  else if (reason == svn_wc_conflict_reason_unversioned)
-    {
-      /* Obstructed by an unversioned node. Source-left is
-       * non-existent/empty. */
-      left_kind = svn_node_none;
-      left_revision = SVN_INVALID_REVNUM;
-      left_repos_relpath = NULL;
-    }
-  else
-    {
-      /* A BASE node should exist. */
-      svn_kind_t base_kind;
-
-      /* If anything else shows up, then this assertion is probably naive
-       * and that other case should also be handled. */
-      SVN_ERR_ASSERT(reason == svn_wc_conflict_reason_edited
-                     || reason == svn_wc_conflict_reason_deleted
-                     || reason == svn_wc_conflict_reason_moved_away
-                     || reason == svn_wc_conflict_reason_moved_away_and_edited
-                     || reason == svn_wc_conflict_reason_replaced
-                     || reason == svn_wc_conflict_reason_obstructed);
-
-      SVN_ERR(svn_wc__db_base_get_info(NULL, &base_kind,
-                                       &left_revision,
-                                       &left_repos_relpath,
-                                       NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL,
-                                       eb->db, local_abspath,
-                                       result_pool, scratch_pool));
-      /* Translate the node kind. */
-      if (base_kind == svn_kind_file
-          || base_kind == svn_kind_symlink)
-        left_kind = svn_node_file;
-      else if (base_kind == svn_kind_dir)
-        left_kind = svn_node_dir;
-      else
-        SVN_ERR_MALFUNCTION();
-    }
-
-  /* Construct the tree conflict info structs. */
-
-  if (left_repos_relpath == NULL)
-    /* A locally added or unversioned path in conflict with an incoming add.
-     * Send an 'empty' left revision. */
-    src_left_version = NULL;
-  else
-    src_left_version = svn_wc_conflict_version_create2(eb->repos_root,
-                                                       eb->repos_uuid,
-                                                       left_repos_relpath,
-                                                       left_revision,
-                                                       left_kind,
-                                                       result_pool);
-
-  *pconflict = svn_wc__conflict_skel_create(result_pool);
-
-  SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(*pconflict,
-                                                  eb->db, local_abspath,
-                                                  reason,
-                                                  action,
-                                                  result_pool, scratch_pool));
-
-  if (eb->switch_relpath)
-    SVN_ERR(svn_wc__conflict_skel_set_op_switch(*pconflict,
-                                                src_left_version,
-                                                result_pool, scratch_pool));
-  else
-    SVN_ERR(svn_wc__conflict_skel_set_op_update(*pconflict,
-                                                src_left_version,
-                                                result_pool, scratch_pool));
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Check whether the incoming change ACTION on FULL_PATH would conflict with
  * LOCAL_ABSPATH's scheduled change. If so, then raise a tree conflict with
  * LOCAL_ABSPATH as the victim.
@@ -1431,7 +1365,7 @@ create_tree_conflict(svn_skel_t **pconfl
  * while *PCONFLICT is always overwritten.
  *
  * The tree conflict is allocated in RESULT_POOL. Temporary allocations use
- * SCRACTH_POOl.
+ * SCRATCH_POOL.
  */
 static svn_error_t *
 check_tree_conflict(svn_skel_t **pconflict,
@@ -1609,11 +1543,16 @@ check_tree_conflict(svn_skel_t **pconfli
     SVN_ERR_ASSERT(action == svn_wc_conflict_action_add);
 
 
-  /* A conflict was detected. Append log commands to the log accumulator
-   * to record it. */
-  return svn_error_trace(create_tree_conflict(pconflict, eb, local_abspath,
-                                              reason, action,
-                                              result_pool, scratch_pool));
+  /* A conflict was detected. Create a conflict skel to record it. */
+  *pconflict = svn_wc__conflict_skel_create(result_pool);
+
+  SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(*pconflict,
+                                                  eb->db, local_abspath,
+                                                  reason,
+                                                  action,
+                                                  result_pool, scratch_pool));
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -1697,8 +1636,8 @@ delete_entry(const char *path,
   const char *repos_relpath;
   const char *moved_to_abspath = NULL;
   svn_kind_t kind, base_kind;
+  svn_revnum_t old_revision;
   svn_boolean_t conflicted;
-  svn_boolean_t have_base;
   svn_boolean_t have_work;
   svn_skel_t *tree_conflict = NULL;
   svn_wc__db_status_t status;
@@ -1739,11 +1678,11 @@ delete_entry(const char *path,
       }
   }
 
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, &repos_relpath, NULL, NULL,
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, &old_revision, &repos_relpath,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, &conflicted,
-                               NULL, NULL, NULL,
-                               &have_base, NULL, &have_work,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               &conflicted, NULL, NULL, NULL,
+                               NULL, NULL, &have_work,
                                eb->db, local_abspath,
                                scratch_pool, scratch_pool));
 
@@ -1753,7 +1692,7 @@ delete_entry(const char *path,
       base_kind = kind;
     }
   else
-    SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, NULL,
+    SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, &old_revision,
                                      &repos_relpath,
                                      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                      NULL, NULL, NULL, NULL,
@@ -1884,6 +1823,13 @@ delete_entry(const char *path,
         SVN_ERR(svn_io_remove_file2(moved_to_abspath, TRUE, scratch_pool));
     }
 
+  SVN_ERR(complete_conflict(tree_conflict, pb, local_abspath, repos_relpath,
+                            old_revision,
+                            (kind == svn_kind_dir)
+                                ? svn_node_dir
+                                : svn_node_file,
+                            pb->pool, scratch_pool));
+
   /* Issue a wq operation to delete the BASE_NODE data and to delete actual
      nodes based on that from disk, but leave any WORKING_NODEs on disk.
 
@@ -2108,11 +2054,10 @@ add_directory(const char *path,
 
           /* And now stop checking for conflicts here and just perform
              a shadowed update */
+          db->edit_conflict = tree_conflict; /* Cache for close_directory */
           tree_conflict = NULL; /* No direct notification */
           db->shadowed = TRUE; /* Just continue */
           conflicted = FALSE; /* No skip */
-
-          db->edit_conflict = tree_conflict; /* Cache for close_directory */
         }
       else
         SVN_ERR(node_already_conflicted(&conflicted, eb->db,
@@ -2223,15 +2168,22 @@ add_directory(const char *path,
           db->shadowed = TRUE;
 
           /* Mark a conflict */
-          SVN_ERR(create_tree_conflict(&tree_conflict, eb,
-                                       db->local_abspath,
-                                       svn_wc_conflict_reason_unversioned,
-                                       svn_wc_conflict_action_add,
-                                       pool, pool));
-          SVN_ERR_ASSERT(tree_conflict != NULL);
+          tree_conflict = svn_wc__conflict_skel_create(db->pool);
+
+          SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+                                        tree_conflict,
+                                        eb->db, db->local_abspath,
+                                        svn_wc_conflict_reason_unversioned,
+                                        svn_wc_conflict_action_add,
+                                        db->pool, pool));
+          db->edit_conflict = tree_conflict;
         }
     }
 
+  SVN_ERR(complete_conflict(tree_conflict, pb, db->local_abspath,
+                            db->old_repos_relpath, db->old_revision,
+                            svn_node_dir, db->pool, pool));
+
   SVN_ERR(svn_wc__db_base_add_incomplete_directory(
                                      eb->db, db->local_abspath,
                                      db->new_relpath,
@@ -2834,41 +2786,14 @@ close_directory(void *dir_baton,
       if (conflict_skel)
         {
           svn_skel_t *work_item;
-          svn_boolean_t completed;
 
-          SVN_ERR(svn_wc__conflict_skel_is_complete(&completed,
-                                                    conflict_skel));
-
-          if (completed)
-            {
-              /* Avoid assertion */
-            }
-          else if (eb->switch_relpath)
-            SVN_ERR(svn_wc__conflict_skel_set_op_switch(
-                        conflict_skel,
-                        db->adding_dir
-                            ? NULL
-                            : svn_wc_conflict_version_create2(
-                                            eb->repos_root,
-                                            eb->repos_uuid,
-                                            db->old_repos_relpath,
-                                            db->old_revision,
-                                            svn_node_dir,
-                                            scratch_pool),
-                        db->pool, db->pool));
-          else
-            SVN_ERR(svn_wc__conflict_skel_set_op_update(
-                        conflict_skel,
-                        db->adding_dir
-                            ? NULL
-                            : svn_wc_conflict_version_create2(
-                                            eb->repos_root,
-                                            eb->repos_uuid,
-                                            db->old_repos_relpath,
-                                            db->old_revision,
-                                            svn_node_dir,
-                                            scratch_pool),
-                        db->pool, db->pool));
+          SVN_ERR(complete_conflict(conflict_skel,
+                                    db->parent_baton,
+                                    db->local_abspath,
+                                    db->old_repos_relpath,
+                                    db->old_revision,
+                                    svn_node_dir,
+                                    db->pool, scratch_pool));
 
           SVN_ERR(svn_wc__conflict_create_markers(&work_item,
                                                   eb->db, db->local_abspath,
@@ -3261,11 +3186,10 @@ add_file(const char *path,
 
           /* And now stop checking for conflicts here and just perform
              a shadowed update */
+          fb->edit_conflict = tree_conflict; /* Cache for close_file */
           tree_conflict = NULL; /* No direct notification */
           fb->shadowed = TRUE; /* Just continue */
           conflicted = FALSE; /* No skip */
-
-          fb->edit_conflict = tree_conflict; /* Cache for close_file */
         }
       else
         SVN_ERR(node_already_conflicted(&conflicted, eb->db,
@@ -3373,12 +3297,14 @@ add_file(const char *path,
           fb->shadowed = TRUE;
 
           /* Mark a conflict */
-          SVN_ERR(create_tree_conflict(&tree_conflict, eb,
-                                       fb->local_abspath,
-                                       svn_wc_conflict_reason_unversioned,
-                                       svn_wc_conflict_action_add,
-                                       scratch_pool, scratch_pool));
-          SVN_ERR_ASSERT(tree_conflict != NULL);
+          tree_conflict = svn_wc__conflict_skel_create(fb->pool);
+
+          SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(
+                                        tree_conflict,
+                                        eb->db, fb->local_abspath,
+                                        svn_wc_conflict_reason_unversioned,
+                                        svn_wc_conflict_action_add,
+                                        fb->pool, scratch_pool));
         }
     }
 
@@ -3395,6 +3321,14 @@ add_file(const char *path,
 
   if (tree_conflict != NULL)
     {
+      SVN_ERR(complete_conflict(tree_conflict,
+                                fb->dir_baton,
+                                fb->local_abspath,
+                                fb->old_repos_relpath,
+                                fb->old_revision,
+                                svn_node_file,
+                                fb->pool, scratch_pool));
+
       SVN_ERR(svn_wc__db_op_mark_conflict(eb->db,
                                           fb->local_abspath,
                                           tree_conflict, NULL,
@@ -4462,39 +4396,13 @@ close_file(void *file_baton,
 
   if (conflict_skel)
     {
-      svn_boolean_t completed;
-
-      SVN_ERR(svn_wc__conflict_skel_is_complete(&completed,
-                                                    conflict_skel));
-
-      if (completed)
-        {
-          /* Avoid assertion */
-        }
-      else if (eb->switch_relpath)
-        SVN_ERR(svn_wc__conflict_skel_set_op_switch(
-                    conflict_skel,
-                    fb->adding_file
-                      ? NULL
-                      : svn_wc_conflict_version_create2(eb->repos_root,
-                                                        eb->repos_uuid,
-                                                        fb->old_repos_relpath,
-                                                        fb->old_revision,
-                                                        svn_node_file,
-                                                        fb->pool),
-                    fb->pool, fb->pool));
-      else
-        SVN_ERR(svn_wc__conflict_skel_set_op_update(
-                    conflict_skel,
-                    fb->adding_file
-                      ? NULL
-                      : svn_wc_conflict_version_create2(eb->repos_root,
-                                                        eb->repos_uuid,
-                                                        fb->old_repos_relpath,
-                                                        fb->old_revision,
-                                                        svn_node_file,
-                                                        fb->pool),
-                    fb->pool, fb->pool));
+      SVN_ERR(complete_conflict(conflict_skel,
+                                fb->dir_baton,
+                                fb->local_abspath,
+                                fb->old_repos_relpath,
+                                fb->old_revision,
+                                svn_node_file,
+                                fb->pool, scratch_pool));
 
       SVN_ERR(svn_wc__conflict_create_markers(&work_item,
                                               eb->db, fb->local_abspath,