You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2013/01/14 20:03:06 UTC

svn commit: r1433046 - in /subversion/trunk/subversion: libsvn_delta/editor.c libsvn_wc/wc_db_update_move.c

Author: philip
Date: Mon Jan 14 19:03:06 2013
New Revision: 1433046

URL: http://svn.apache.org/viewvc?rev=1433046&view=rev
Log:
Make the move-update drive more Ev2-like by only calling the alter
functions when there are changes.  I had to disable the Ev2 debug 
ordering code as the checks don't seem to be valid.

* subversion/libsvn_delta/editor.c
  (ENABLE_ORDERING_CHECK): Don't define.
  (svn_editor_alter_directory): Add suggestion in comment.

* subversion/libsvn_wc/wc_db_update_move.c
  (get_info, children_match, props_match): New.
  (update_moved_away_file, update_moved_away_dir,
   update_moved_away_subtree): Remove, replaced by...
  (update_moved_away_node): ... this.
  (drive_tree_conflict_editor): Call update_moved_away_node.

Modified:
    subversion/trunk/subversion/libsvn_delta/editor.c
    subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c

Modified: subversion/trunk/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_delta/editor.c?rev=1433046&r1=1433045&r2=1433046&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_delta/editor.c (original)
+++ subversion/trunk/subversion/libsvn_delta/editor.c Mon Jan 14 19:03:06 2013
@@ -35,9 +35,18 @@
    introduce additional memory and runtime overhead, and should not be used
    in production builds.
 
-   ### Remove before release? */
+   ### Remove before release? 
+
+   ### Disabled for now.  If I call svn_editor_alter_directory(A) then
+       svn_editor_add_file(A/f) the latter fails on SHOULD_ALLOW_ADD.
+       If I modify svn_editor_alter_directory to MARK_ALLOW_ADD(child)
+       then if I call svn_editor_alter_directory(A) followed by
+       svn_editor_alter_directory(A/B/C) the latter fails on
+       VERIFY_PARENT_MAY_EXIST. */
+#if 0
 #define ENABLE_ORDERING_CHECK
 #endif
+#endif
 
 
 struct svn_editor_t
@@ -666,6 +675,7 @@ svn_editor_alter_directory(svn_editor_t 
 
         apr_hash_set(editor->pending_incomplete_children, child,
                      APR_HASH_KEY_STRING, "");
+        /* Perhaps MARK_ALLOW_ADD(editor, child); ? */
       }
   }
 #endif

Modified: subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c?rev=1433046&r1=1433045&r2=1433046&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db_update_move.c Mon Jan 14 19:03:06 2013
@@ -77,6 +77,7 @@
 #include "svn_wc.h"
 #include "svn_props.h"
 #include "svn_pools.h"
+#include "svn_sorts.h"
 
 #include "private/svn_skel.h"
 #include "private/svn_sqlite.h"
@@ -961,188 +962,263 @@ get_tc_info(svn_wc_operation_t *operatio
   return SVN_NO_ERROR;
 }
 
-/* ### Drive TC_EDITOR so as to ...
- */
-static svn_error_t *
-update_moved_away_file(svn_editor_t *tc_editor,
-                       svn_boolean_t add,
-                       const char *src_relpath,
-                       const char *dst_relpath,
-                       const char *move_root_dst_relpath,
-                       svn_revnum_t move_root_dst_revision,
-                       svn_wc__db_t *db,
-                       svn_wc__db_wcroot_t *wcroot,
-                       apr_pool_t *scratch_pool)
+/* Return *PROPS, *CHECKSUM, *CHILDREN and *KIND for LOCAL_RELPATH at
+   OP_DEPTH provided the row exists.  Return *KIND of svn_kind_none if
+   the row does not exist. *CHILDREN is a sorted array of basenames of
+   type 'const char *', rather than a hash, to allow the driver to
+   process children in a defined order. */
+static svn_error_t *
+get_info(apr_hash_t **props,
+         const svn_checksum_t **checksum,
+         apr_array_header_t **children,
+         svn_kind_t *kind,
+         const char *local_relpath,
+         int op_depth,
+         svn_wc__db_wcroot_t *wcroot,
+         apr_pool_t *result_pool,
+         apr_pool_t *scratch_pool)
 {
-  svn_kind_t kind;
-  svn_stream_t *new_contents;
-  const svn_checksum_t *new_checksum;
-  apr_hash_t *new_props;
-
-  /* Read post-update contents from the updated moved-away file and tell
-   * the editor to merge them into the moved-here file. */
-  SVN_ERR(svn_wc__db_read_pristine_info(NULL, &kind, NULL, NULL, NULL, NULL,
-                                        &new_checksum, NULL, NULL, &new_props,
-                                        db, svn_dirent_join(wcroot->abspath,
-                                                            src_relpath,
-                                                            scratch_pool),
-                                        scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__db_pristine_read(&new_contents, NULL, db,
-                                   wcroot->abspath, new_checksum,
-                                   scratch_pool, scratch_pool));
+  svn_sqlite__stmt_t *stmt;
+  apr_hash_t *hash_children;
+  apr_array_header_t *sorted_children;
+  svn_boolean_t have_row;
+  int i;
 
-  if (add)
-    /* FIXME: editor API violation: missing svn_editor_alter_directory. */
-    SVN_ERR(svn_editor_add_file(tc_editor, dst_relpath,
-                                new_checksum, new_contents,
-                                apr_hash_make(scratch_pool), /* ### TODO props */
-                                move_root_dst_revision));
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_DEPTH_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                            local_relpath, op_depth));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    {
+      svn_error_t *err;
+
+      *kind = svn_sqlite__column_token(stmt, 3, kind_map);
+      err = svn_sqlite__column_properties(props, stmt, 13,
+                                          result_pool, scratch_pool);
+      if (!err)
+        err = svn_sqlite__column_checksum(checksum, stmt, 5, result_pool);
+      if (err)
+        return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+    }
   else
-    SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
-                                  move_root_dst_revision,
-                                  new_props, new_checksum,
-                                  new_contents));
+    *kind = svn_kind_none;
+  SVN_ERR(svn_sqlite__reset(stmt));
+  
+  SVN_ERR(svn_wc__db_get_children_op_depth(&hash_children, wcroot,
+                                           local_relpath, op_depth,
+                                           scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_stream_close(new_contents));
+  sorted_children = svn_sort__hash(hash_children,
+                                   svn_sort_compare_items_as_paths,
+                                   scratch_pool);
 
+  *children = apr_array_make(result_pool, sorted_children->nelts,
+                             sizeof(const char *));
+  for (i = 0; i < sorted_children->nelts; ++i)
+    APR_ARRAY_PUSH(*children, const char *)
+      = apr_pstrdup(result_pool, APR_ARRAY_IDX(sorted_children, i,
+                                               svn_sort__item_t).key);
+                                                           
   return SVN_NO_ERROR;
 }
 
-/* ### Drive TC_EDITOR so as to ...
- */
+/* Return TRUE if SRC_CHILDREN and DST_CHILDREN represent the same
+   children, FALSE otherwise.  SRC_CHILDREN and DST_CHILDREN are
+   sorted arrays of basenames of type 'const char *'. */
+static svn_boolean_t
+children_match(apr_array_header_t *src_children,
+               apr_array_header_t *dst_children) { int i;
+
+  if (src_children->nelts != dst_children->nelts)
+    return FALSE;
+
+  for(i = 0; i < src_children->nelts; ++i)
+    {
+      const char *src_child =
+        APR_ARRAY_IDX(src_children, i, const char *);
+      const char *dst_child =
+        APR_ARRAY_IDX(dst_children, i, const char *);
+
+      if (strcmp(src_child, dst_child))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Return TRUE if SRC_PROPS and DST_PROPS contain the same properties,
+   FALSE otherwise. SRC_PROPS and DST_PROPS are standard property
+   hashes. */
 static svn_error_t *
-update_moved_away_dir(svn_editor_t *tc_editor,
-                      svn_boolean_t add,
-                      apr_hash_t *children_hash,
-                      const char *src_relpath,
-                      const char *dst_relpath,
-                      const char *move_root_dst_relpath,
-                      svn_revnum_t move_root_dst_revision,
-                      svn_wc__db_t *db,
-                      svn_wc__db_wcroot_t *wcroot,
-                      apr_pool_t *scratch_pool)
+props_match(svn_boolean_t *match,
+            apr_hash_t *src_props,
+            apr_hash_t *dst_props,
+            apr_pool_t *scratch_pool)
 {
-  apr_array_header_t *new_children;
-  apr_hash_t *new_props;
-  const char *src_abspath = svn_dirent_join(wcroot->abspath,
-                                            src_relpath,
-                                            scratch_pool);
-
-  SVN_ERR(svn_hash_keys(&new_children, children_hash, scratch_pool));
-
-  SVN_ERR(svn_wc__db_read_pristine_props(&new_props, db, src_abspath,
-                                         scratch_pool, scratch_pool));
-
-  /* This is a non-Ev2, depth-first, drive that calls add/alter on all
-     directories. */
-  if (add)
-    SVN_ERR(svn_editor_add_directory(tc_editor, dst_relpath,
-                                     new_children, new_props,
-                                     move_root_dst_revision));
+  if (!src_props && !dst_props)
+    *match = TRUE;
+  else if (!src_props || ! dst_props)
+    *match = FALSE;
   else
-    SVN_ERR(svn_editor_alter_directory(tc_editor, dst_relpath,
-                                       move_root_dst_revision,
-                                       new_children, new_props));
+    {
+      apr_array_header_t *propdiffs;
 
+      SVN_ERR(svn_prop_diffs(&propdiffs, src_props, dst_props, scratch_pool));
+      *match = propdiffs->nelts ? FALSE : TRUE;
+    }
   return SVN_NO_ERROR;
 }
 
 /* ### Drive TC_EDITOR so as to ...
  */
 static svn_error_t *
-update_moved_away_subtree(svn_editor_t *tc_editor,
-                          svn_boolean_t add,
-                          const char *src_relpath,
-                          const char *dst_relpath,
-                          int src_op_depth,
-                          const char *move_root_dst_relpath,
-                          svn_revnum_t move_root_dst_revision,
-                          svn_wc__db_t *db,
-                          svn_wc__db_wcroot_t *wcroot,
-                          apr_pool_t *scratch_pool)
+update_moved_away_node(svn_editor_t *tc_editor,
+                       const char *src_relpath,
+                       const char *dst_relpath,
+                       int src_op_depth,
+                       const char *move_root_dst_relpath,
+                       svn_revnum_t move_root_dst_revision,
+                       svn_wc__db_t *db,
+                       svn_wc__db_wcroot_t *wcroot,
+                       apr_pool_t *scratch_pool)
 {
-  apr_hash_t *src_children, *dst_children;
-  apr_pool_t *iterpool;
-  apr_hash_index_t *hi;
+  svn_kind_t src_kind, dst_kind;
+  const svn_checksum_t *src_checksum, *dst_checksum;
+  apr_hash_t *src_props, *dst_props;
+  apr_array_header_t *src_children, *dst_children;
+  int dst_op_depth = relpath_depth(move_root_dst_relpath);
+
+  SVN_ERR(get_info(&src_props, &src_checksum, &src_children, &src_kind,
+                   src_relpath, src_op_depth,
+                   wcroot, scratch_pool, scratch_pool));
+
+  SVN_ERR(get_info(&dst_props, &dst_checksum, &dst_children, &dst_kind,
+                   dst_relpath, dst_op_depth,
+                   wcroot, scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_wc__db_get_children_op_depth(&src_children, wcroot,
-                                           src_relpath, src_op_depth,
-                                           scratch_pool, scratch_pool));
+  if (src_kind == svn_kind_none
+      || (dst_kind != svn_kind_none && src_kind != dst_kind))
+    {
+      SVN_ERR(svn_editor_delete(tc_editor, dst_relpath,
+                                move_root_dst_revision));
+    }
+ 
+  if (src_kind != svn_kind_none && src_kind != dst_kind)
+    {
+      if (src_kind == svn_kind_file || src_kind == svn_kind_symlink)
+        {
+          svn_stream_t *contents;
 
-  SVN_ERR(update_moved_away_dir(tc_editor, add, src_children,
-                                src_relpath, dst_relpath,
-                                move_root_dst_relpath,
-                                move_root_dst_revision,
-                                db, wcroot, scratch_pool));
-
-  SVN_ERR(svn_wc__db_get_children_op_depth(&dst_children, wcroot,
-                                           dst_relpath,
-                                           relpath_depth(move_root_dst_relpath),
+          SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, db,
+                                           wcroot->abspath, src_checksum,
                                            scratch_pool, scratch_pool));
-  iterpool = svn_pool_create(scratch_pool);
-  for (hi = apr_hash_first(scratch_pool, src_children);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const char *src_name = svn__apr_hash_index_key(hi);
-      svn_kind_t *src_kind = svn__apr_hash_index_val(hi);
-      svn_kind_t *dst_kind = apr_hash_get(dst_children, src_name,
-                                          APR_HASH_KEY_STRING);
-      svn_boolean_t is_add = FALSE;
-      const char *child_src_relpath, *child_dst_relpath;
-
-      svn_pool_clear(iterpool);
-
-      child_src_relpath = svn_relpath_join(src_relpath, src_name, iterpool);
-      child_dst_relpath = svn_relpath_join(dst_relpath, src_name, iterpool);
-
-      if (!dst_kind || (*src_kind != *dst_kind))
-        {
-          is_add = TRUE;
-          if (dst_kind)
-            /* FIXME:editor API violation:missing svn_editor_alter_directory. */
-            SVN_ERR(svn_editor_delete(tc_editor, child_dst_relpath,
+          SVN_ERR(svn_editor_add_file(tc_editor, dst_relpath,
+                                      src_checksum, contents, src_props,
                                       move_root_dst_revision));
         }
-
-      if (*src_kind == svn_kind_file || *src_kind == svn_kind_symlink)
+      else if (src_kind == svn_kind_dir)
         {
-          SVN_ERR(update_moved_away_file(tc_editor, is_add,
-                                         child_src_relpath,
-                                         child_dst_relpath,
-                                         move_root_dst_relpath,
-                                         move_root_dst_revision,
-                                         db, wcroot, iterpool));
+          SVN_ERR(svn_editor_add_directory(tc_editor, dst_relpath,
+                                           src_children, src_props,
+                                           move_root_dst_revision));
         }
-      else if (*src_kind == svn_kind_dir)
+    }
+  else if (src_kind != svn_kind_none)
+    {
+      svn_boolean_t match;
+      apr_hash_t *props;
+
+      SVN_ERR(props_match(&match, src_props, dst_props, scratch_pool));
+      props = match ? NULL: src_props;
+
+      
+      if (src_kind == svn_kind_file || src_kind == svn_kind_symlink)
         {
-          SVN_ERR(update_moved_away_subtree(tc_editor, is_add,
-                                            child_src_relpath,
-                                            child_dst_relpath,
-                                            src_op_depth,
-                                            move_root_dst_relpath,
-                                            move_root_dst_revision,
-                                            db, wcroot, iterpool));
+          svn_stream_t *contents;
+
+          if (svn_checksum_match(src_checksum, dst_checksum))
+            src_checksum = NULL;
+
+          if (src_checksum)
+            SVN_ERR(svn_wc__db_pristine_read(&contents, NULL, db,
+                                             wcroot->abspath, src_checksum,
+                                             scratch_pool, scratch_pool));
+          else
+            contents = NULL;
+
+          if (props || src_checksum)
+            SVN_ERR(svn_editor_alter_file(tc_editor, dst_relpath,
+                                          move_root_dst_revision,
+                                          props, src_checksum, contents));
         }
-      else
-        ; /* ### TODO */
+      else if (src_kind == svn_kind_dir)
+        {
+          apr_array_header_t *children
+            = children_match(src_children, dst_children) ? NULL : src_children;
 
-      apr_hash_set(dst_children, src_name, APR_HASH_KEY_STRING, NULL);
+          if (props || children)
+            SVN_ERR(svn_editor_alter_directory(tc_editor, dst_relpath,
+                                               move_root_dst_revision,
+                                               children, props));
+        }
     }
-  for (hi = apr_hash_first(scratch_pool, dst_children);
-       hi;
-       hi = apr_hash_next(hi))
+
+  if (src_kind == svn_kind_dir)
     {
-      const char *dst_name = svn__apr_hash_index_key(hi);
-      const char *child_dst_relpath;
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+      int i = 0, j = 0;
 
-      svn_pool_clear(iterpool);
-      child_dst_relpath = svn_relpath_join(dst_relpath, dst_name, iterpool);
+      while (i < src_children->nelts || j < dst_children->nelts)
+        {
+          const char *child_name;
+          const char *src_child_relpath, *dst_child_relpath;
+          svn_boolean_t src_only = FALSE, dst_only = FALSE;
 
-      SVN_ERR(svn_editor_delete(tc_editor, child_dst_relpath,
-                                move_root_dst_revision));
+          svn_pool_clear(iterpool);
+          if (i >= src_children->nelts)
+            {
+              dst_only = TRUE;
+              child_name = APR_ARRAY_IDX(dst_children, j, const char *);
+            }
+          else if (j >= dst_children->nelts)
+            {
+              src_only = TRUE;
+              child_name = APR_ARRAY_IDX(src_children, i, const char *);
+            }
+          else
+            {
+              const char *src_name = APR_ARRAY_IDX(src_children, i,
+                                                   const char *);
+              const char *dst_name = APR_ARRAY_IDX(dst_children, j,
+                                                   const char *);
+              int cmp = strcmp(src_name, dst_name);
+
+              if (cmp > 0)
+                dst_only = TRUE;
+              else if (cmp < 0)
+                src_only = TRUE;
+
+              child_name = dst_only ? dst_name : src_name;
+            }
+
+          src_child_relpath = svn_relpath_join(src_relpath, child_name,
+                                               iterpool);
+          dst_child_relpath = svn_relpath_join(dst_relpath, child_name,
+                                               iterpool);
+
+          SVN_ERR(update_moved_away_node(tc_editor, src_child_relpath,
+                                         dst_child_relpath, src_op_depth,
+                                         move_root_dst_relpath,
+                                         move_root_dst_revision,
+                                         db, wcroot, scratch_pool));
+
+          if (!dst_only)
+            ++i;
+          if (!src_only)
+            ++j;
+        }
     }
-  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -1241,16 +1317,10 @@ drive_tree_conflict_editor(svn_editor_t 
   /* We walk the move source (i.e. the post-update tree), comparing each node
    * with the equivalent node at the move destination and applying the update
    * to nodes at the move destination. */
-  if (old_version->node_kind == svn_node_file)
-    SVN_ERR(update_moved_away_file(tc_editor, FALSE, src_relpath, dst_relpath,
-                                   dst_relpath, old_version->peg_rev,
-                                   db, wcroot, scratch_pool));
-  else if (old_version->node_kind == svn_node_dir)
-    SVN_ERR(update_moved_away_subtree(tc_editor, FALSE,
-                                      src_relpath, dst_relpath,
-                                      src_op_depth,
-                                      dst_relpath, old_version->peg_rev,
-                                      db, wcroot, scratch_pool));
+  SVN_ERR(update_moved_away_node(tc_editor, src_relpath, dst_relpath,
+                                 src_op_depth,
+                                 dst_relpath, old_version->peg_rev,
+                                 db, wcroot, scratch_pool));
 
   SVN_ERR(svn_editor_complete(tc_editor));