You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ar...@apache.org on 2010/08/06 09:41:51 UTC

svn commit: r982900 - in /subversion/trunk/subversion/svnrdump: load_editor.c load_editor.h

Author: artagnon
Date: Fri Aug  6 07:41:51 2010
New Revision: 982900

URL: http://svn.apache.org/viewvc?rev=982900&view=rev
Log:
svnrdump: Make the load editor respect the rules of an
svn_delta_editor_t strictly by calling open_directory and
close_directory where appropriate.

* subversion/svnrdump/load_editor.h

  (parse_baton): Remove pool and use the one in the revision_baton
  instead.

  (directory_baton): New structure to wrap the unexposed dir_context_t
  in commit.c. This is useful to keep track of how deep our directory
  baton is and provide a link the the parent.

  (revision_baton): Change the type of the directory baton from void *
  to struct directory_baton *.

* subversion/svnrdump/load_editor.c

  (new_revision_record, new_node_record, set_revision_property,
  set_node_property, delete_node_property, apply_textdelta,
  close_revision): Track the change in the pool's location.

  (new_node_record): While creating the commit_editor, also create a
  toplevel directory baton. Add some logic to open and close
  directories and set the directory baton appropriately depending on
  how much the dirname of the file we're adding differs from the our
  current directory baton's path.

  (close_revision): Close any open directories before closing the edit
  session itself.

Modified:
    subversion/trunk/subversion/svnrdump/load_editor.c
    subversion/trunk/subversion/svnrdump/load_editor.h

Modified: subversion/trunk/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnrdump/load_editor.c?rev=982900&r1=982899&r2=982900&view=diff
==============================================================================
--- subversion/trunk/subversion/svnrdump/load_editor.c (original)
+++ subversion/trunk/subversion/svnrdump/load_editor.c Fri Aug  6 07:41:51 2010
@@ -56,7 +56,7 @@ new_revision_record(void **revision_bato
 
   rb = apr_pcalloc(pool, sizeof(*rb));
   pb = parse_baton;
-  pb->pool = svn_pool_create(pool);
+  rb->pool = svn_pool_create(pool);
   rb->pb = pb;
 
   for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi))
@@ -72,12 +72,12 @@ new_revision_record(void **revision_bato
       if (strcmp(hname, SVN_REPOS_DUMPFILE_REVISION_NUMBER) == 0)
         rb->rev = atoi(hval);
     }
+
   /* Set the commit_editor/ commit_edit_baton to NULL and wait for
      them to be created in new_node_record */
-  
   rb->pb->commit_editor = NULL;
   rb->pb->commit_edit_baton = NULL;
-  rb->revprop_table = apr_hash_make(pb->pool);
+  rb->revprop_table = apr_hash_make(rb->pool);
 
   *revision_baton = rb;
   return SVN_NO_ERROR;
@@ -100,17 +100,19 @@ new_node_record(void **node_baton,
                 void *revision_baton,
                 apr_pool_t *pool)
 {
+  const struct svn_delta_editor_t *commit_editor;
   struct node_baton *nb;
   struct revision_baton *rb;
+  struct directory_baton *child_db;
   apr_hash_index_t *hi;
-  void *file_baton;
   void *child_baton;
-  const struct svn_delta_editor_t *commit_editor;
   void *commit_edit_baton;
-  void *root_baton;
+  char *ancestor_path;
+  apr_array_header_t *residual_path;
+  int i;
 
   rb = revision_baton;
-  nb = apr_pcalloc(rb->pb->pool, sizeof(*nb));
+  nb = apr_pcalloc(rb->pool, sizeof(*nb));
   nb->rb = rb;
 
   nb->copyfrom_path = NULL;
@@ -120,23 +122,29 @@ new_node_record(void **node_baton,
   commit_edit_baton = rb->pb->commit_edit_baton;
 
   /* If the creation of commit_editor is pending, create it now and
-     open_root on it */
+     open_root on it; also create a top-level directory baton. */
   if (!commit_editor) {
       SVN_ERR(svn_ra_get_commit_editor3(rb->pb->session, &commit_editor,
                                         &commit_edit_baton, rb->revprop_table,
                                         commit_callback, NULL, NULL, FALSE,
-                                        rb->pb->pool));
+                                        rb->pool));
 
       rb->pb->commit_editor = commit_editor;
       rb->pb->commit_edit_baton = commit_edit_baton;
 
       SVN_ERR(commit_editor->open_root(commit_edit_baton, rb->rev - 1,
-                                       rb->pb->pool, &root_baton));
-      rb->dir_baton = root_baton;
+                                       rb->pool, &child_baton));
 
+      /* child_db corresponds to the root directory baton here */
+      child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
+      child_db->baton = child_baton;
+      child_db->depth = 0;
+      child_db->parent = NULL;
+      child_db->relpath = apr_pstrdup(rb->pool, "/");
+      rb->db = child_db;
   }
 
-  for (hi = apr_hash_first(rb->pb->pool, headers); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(rb->pool, headers); hi; hi = apr_hash_next(hi))
     {
       const void *key;
       void *val;
@@ -149,7 +157,7 @@ new_node_record(void **node_baton,
       /* Parse the different kinds of headers we can encounter and
          stuff them into the node_baton for writing later */
       if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_PATH) == 0)
-        nb->path = apr_pstrdup(rb->pb->pool, hval);
+        nb->path = apr_pstrdup(rb->pool, hval);
       if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_KIND) == 0)
         nb->kind = strcmp(hval, "file") == 0 ? svn_node_file : svn_node_dir;
       if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_ACTION) == 0)
@@ -168,8 +176,50 @@ new_node_record(void **node_baton,
       if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH) == 0)
           nb->copyfrom_path =
             svn_path_url_add_component2(rb->pb->root_url,
-                                        apr_pstrdup(rb->pb->pool, hval),
-                                        rb->pb->pool);
+                                        apr_pstrdup(rb->pool, hval),
+                                        rb->pool);
+    }
+
+  if (svn_path_compare_paths(svn_relpath_dirname(nb->path, pool),
+                             rb->db->baton) != 0)
+    {
+      /* Before attempting to handle the action, call open_directory
+         for all the path components and set the directory baton
+         accordingly */
+      ancestor_path =
+        svn_relpath_get_longest_ancestor(nb->path,
+                                         rb->db->relpath, pool);
+      residual_path =
+        svn_path_decompose(svn_relpath_skip_ancestor(nb->path,
+                                                     ancestor_path),
+                           rb->pool);
+
+      /* First close all as many directories as there are after
+         skip_ancestor, and then open fresh directories */
+      for (i = 0; i < residual_path->nelts; i ++)
+        {
+          /* Don't worry about destroying the actual rb->db object,
+             since the pool we're using has the lifetime of one
+             revision anyway */
+          SVN_ERR(commit_editor->close_directory(rb->db->baton, rb->pool));
+          rb->db = rb->db->parent;
+        }
+        
+      for (i = 0; i < residual_path->nelts; i ++)
+        {
+          SVN_ERR(commit_editor->open_directory(residual_path->elts + i,
+                                                rb->db->baton,
+                                                rb->rev - 1,
+                                                rb->pool, child_baton));
+          child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
+          child_db->baton = child_baton;
+          child_db->depth = rb->db->depth + 1;
+          child_db->relpath = svn_relpath_join(rb->db->relpath,
+                                               residual_path->elts + i,
+                                               rb->pool);
+          rb->db = child_db;
+        }
+
     }
 
   switch (nb->action)
@@ -178,17 +228,16 @@ new_node_record(void **node_baton,
       switch (nb->kind)
         {
         case svn_node_file:
-          SVN_ERR(commit_editor->add_file(nb->path, rb->dir_baton,
+          SVN_ERR(commit_editor->add_file(nb->path, rb->db->baton,
                                           nb->copyfrom_path,
                                           nb->copyfrom_rev,
-                                          rb->pb->pool, &file_baton));
-          nb->file_baton = file_baton;
+                                          rb->pool, &(nb->file_baton)));
           break;
         case svn_node_dir:
-          SVN_ERR(commit_editor->add_directory(nb->path, rb->dir_baton,
+          SVN_ERR(commit_editor->add_directory(nb->path, rb->db->baton,
                                                nb->copyfrom_path,
                                                nb->copyfrom_rev,
-                                               rb->pb->pool, &child_baton));
+                                               rb->pool, &child_baton));
           break;
         default:
           break;
@@ -201,11 +250,11 @@ new_node_record(void **node_baton,
         {
         case svn_node_file:
           SVN_ERR(commit_editor->delete_entry(nb->path, rb->rev,
-                                              rb->dir_baton, rb->pb->pool));
+                                              rb->db->baton, rb->pool));
           break;
         case svn_node_dir:
           SVN_ERR(commit_editor->delete_entry(nb->path, rb->rev,
-                                              rb->dir_baton, rb->pb->pool));
+                                              rb->db->baton, rb->pool));
           break;
         default:
           break;
@@ -228,20 +277,20 @@ set_revision_property(void *baton,
   rb = baton;
 
   if (rb->rev > 0)
-    apr_hash_set(rb->revprop_table, apr_pstrdup(rb->pb->pool, name),
-                 APR_HASH_KEY_STRING, svn_string_dup(value, rb->pb->pool));
+    apr_hash_set(rb->revprop_table, apr_pstrdup(rb->pool, name),
+                 APR_HASH_KEY_STRING, svn_string_dup(value, rb->pool));
   else
     /* Special handling for revision 0; this is safe because the
        commit_editor hasn't been created yet. */
     svn_ra_change_rev_prop(rb->pb->session, rb->rev, name, value,
-                           rb->pb->pool);
+                           rb->pool);
 
   /* Remember any datestamp/ author that passes through (see comment
      in close_revision). */
   if (!strcmp(name, SVN_PROP_REVISION_DATE))
-    rb->datestamp = svn_string_dup(value, rb->pb->pool);
+    rb->datestamp = svn_string_dup(value, rb->pool);
   if (!strcmp(name, SVN_PROP_REVISION_AUTHOR))
-    rb->author = svn_string_dup(value, rb->pb->pool);
+    rb->author = svn_string_dup(value, rb->pool);
 
   return SVN_NO_ERROR;
 }
@@ -256,13 +305,13 @@ set_node_property(void *baton,
   apr_pool_t *pool;
   nb = baton;
   commit_editor = nb->rb->pb->commit_editor;
-  pool = nb->rb->pb->pool;
+  pool = nb->rb->pool;
 
   if (nb->kind == svn_node_file)
     SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
                                             value, pool));
   else
-    SVN_ERR(commit_editor->change_dir_prop(nb->rb->dir_baton, name,
+    SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
                                            value, pool));
 
   return SVN_NO_ERROR;
@@ -277,13 +326,13 @@ delete_node_property(void *baton,
   apr_pool_t *pool;
   nb = baton;
   commit_editor = nb->rb->pb->commit_editor;
-  pool = nb->rb->pb->pool;
+  pool = nb->rb->pool;
 
   if (nb->kind == svn_node_file)
     SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
                                             NULL, pool));
   else
-    SVN_ERR(commit_editor->change_dir_prop(nb->rb->dir_baton, name,
+    SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
                                            NULL, pool));
 
   return SVN_NO_ERROR;
@@ -314,7 +363,7 @@ apply_textdelta(svn_txdelta_window_handl
   apr_pool_t *pool;
   nb = node_baton;
   commit_editor = nb->rb->pb->commit_editor;
-  pool = nb->rb->pb->pool;
+  pool = nb->rb->pool;
   SVN_ERR(commit_editor->apply_textdelta(nb->file_baton, NULL, pool,
                                          handler, handler_baton));
   SVN_ERR(commit_editor->close_file(nb->file_baton, NULL, pool));
@@ -342,22 +391,28 @@ close_revision(void *baton)
 
   /* r0 doesn't have a corresponding commit_editor; we fake it */
   if (rb->rev == 0)
-    SVN_ERR(svn_cmdline_printf(rb->pb->pool, "* Loaded revision 0\n"));
+    SVN_ERR(svn_cmdline_printf(rb->pool, "* Loaded revision 0\n"));
   else {
-    SVN_ERR(commit_editor->close_directory(rb->dir_baton, rb->pb->pool));
-    SVN_ERR(commit_editor->close_edit(commit_edit_baton, rb->pb->pool));
+    /* Close all pending open directories, and then close the edit
+       session itself */
+    while (rb->db)
+      {
+        SVN_ERR(commit_editor->close_directory(rb->db->baton, rb->pool));
+        rb->db = rb->db->parent;
+      }
+    SVN_ERR(commit_editor->close_edit(commit_edit_baton, rb->pool));
   }
 
   /* svn_fs_commit_txn rewrites the datestamp/ author property-
      rewrite it by hand after closing the commit_editor. */
   SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
                                  SVN_PROP_REVISION_DATE,
-                                 rb->datestamp, rb->pb->pool));
+                                 rb->datestamp, rb->pool));
   SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
                                  SVN_PROP_REVISION_AUTHOR,
-                                 rb->author, rb->pb->pool));
+                                 rb->author, rb->pool));
 
-  svn_pool_destroy(rb->pb->pool);
+  svn_pool_destroy(rb->pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/svnrdump/load_editor.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnrdump/load_editor.h?rev=982900&r1=982899&r2=982900&view=diff
==============================================================================
--- subversion/trunk/subversion/svnrdump/load_editor.h (original)
+++ subversion/trunk/subversion/svnrdump/load_editor.h Fri Aug  6 07:41:51 2010
@@ -38,7 +38,18 @@ struct parse_baton
   svn_ra_session_t *session;
   const char *uuid;
   const char *root_url;
-  apr_pool_t *pool;
+};
+
+/**
+ * Use to wrap the dir_context_t in commit.c so we can keep track of
+ * depth, relpath and parent for open_directory and close_directory.
+ */
+struct directory_baton
+{
+  void *baton;
+  const char *relpath;
+  int depth;
+  struct directory_baton *parent;
 };
 
 /**
@@ -71,8 +82,8 @@ struct revision_baton
   const svn_string_t *author;
 
   struct parse_baton *pb;
+  struct directory_baton *db;
   apr_pool_t *pool;
-  void *dir_baton;                    /* Keep track of dirs */
 };
 
 /**