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 2014/03/31 12:58:20 UTC

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

Author: rhuijben
Date: Mon Mar 31 10:58:19 2014
New Revision: 1583294

URL: http://svn.apache.org/r1583294
Log:
Make the add_directory and add_file code in the update editor more similar and
thereby avoid a few unneeded db operations during a clean checkout.

* subversion/libsvn_wc/update_editor.c
  (dir_baton): Rename variable.
  (make_dir_baton): Update initialization.
  (add_directory): Introduce a real scratch pool. Implement the same clean
    checkout optimization as in add_file. Handle status normal for obstructions
    as one block. Remove comment on 'output' that belongs in svn.
  (close_directory): Handle kind of not present nodes. Remove from parent not
    present if necessary.
  (add_file): Handle status for obstructions as one block.
  (close_file): Update caller.

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=1583294&r1=1583293&r2=1583294&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/update_editor.c Mon Mar 31 10:58:19 2014
@@ -345,9 +345,10 @@ struct dir_baton
      and reinstall it. */
   apr_hash_t *deletion_conflicts;
 
-  /* A hash of file names (only the hash key matters) seen by add_file
-     and not yet added to the database by close_file. */
-  apr_hash_t *not_present_files;
+  /* A hash of file names (only the hash key matters) seen by add_file and
+     add_directory and not yet added to the database, mapping to a const
+     char * node kind (via svn_node_kind_to_word(). */
+  apr_hash_t *not_present_nodes;
 
   /* Set if an unversioned dir of the same name already existed in
      this directory. */
@@ -608,7 +609,7 @@ make_dir_baton(struct dir_baton **d_p,
   d->old_revision = SVN_INVALID_REVNUM;
   d->adding_dir   = adding;
   d->changed_rev  = SVN_INVALID_REVNUM;
-  d->not_present_files = apr_hash_make(dir_pool);
+  d->not_present_nodes = apr_hash_make(dir_pool);
 
   /* Copy some flags from the parent baton */
   if (pb)
@@ -1974,6 +1975,7 @@ add_directory(const char *path,
   struct dir_baton *pb = parent_baton;
   struct edit_baton *eb = pb->edit_baton;
   struct dir_baton *db;
+  apr_pool_t *scratch_pool = svn_pool_create(pool);
   svn_node_kind_t kind;
   svn_wc__db_status_t status;
   svn_node_kind_t wc_kind;
@@ -1987,7 +1989,7 @@ add_directory(const char *path,
 
   SVN_ERR(make_dir_baton(&db, path, eb, pb, TRUE, pool));
   SVN_ERR(calculate_repos_relpath(&db->new_repos_relpath, db->local_abspath,
-                                  NULL, eb, pb, db->pool, pool));
+                                  NULL, eb, pb, db->pool, scratch_pool));
   *child_baton = db;
 
   if (db->skip_this)
@@ -2022,13 +2024,26 @@ add_directory(const char *path,
          "administrative directory"),
        svn_dirent_local_style(db->local_abspath, pool));
 
-  SVN_ERR(svn_io_check_path(db->local_abspath, &kind, db->pool));
+  if (!eb->clean_checkout)
+    {
+      SVN_ERR(svn_io_check_path(db->local_abspath, &kind, db->pool));
+
+      err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
+                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                NULL, NULL, NULL, NULL, NULL,
+                                &conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
+                                eb->db, db->local_abspath,
+                                scratch_pool, scratch_pool);
+    }
+  else
+    {
+      kind = svn_node_none;
+      status = svn_wc__db_status_not_present;
+      wc_kind = svn_node_unknown;
+      conflicted = FALSE;
+      err = NULL;
+    }
 
-  err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                             NULL, NULL, NULL, NULL, NULL,
-                             &conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
-                             eb->db, db->local_abspath, db->pool, db->pool);
   if (err)
     {
       if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
@@ -2041,63 +2056,55 @@ add_directory(const char *path,
 
       versioned_locally_and_present = FALSE;
     }
-  else if (wc_kind == svn_node_dir
-           && status == svn_wc__db_status_normal)
+  else if (status == svn_wc__db_status_normal && wc_kind == svn_node_unknown)
     {
-      /* !! We found the root of a separate working copy obstructing the wc !!
+      SVN_ERR_ASSERT(conflicted);
+      versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
+    }
+  else if (status == svn_wc__db_status_normal)
+    {
+      if (wc_kind == svn_node_dir)
+        {
+          /* !! We found the root of a working copy obstructing the wc !!
 
-         If the directory would be part of our own working copy then
-         we wouldn't have been called as an add_directory().
+             If the directory would be part of our own working copy then
+             we wouldn't have been called as an add_directory().
 
-         The only thing we can do is add a not-present node, to allow
-         a future update to bring in the new files when the problem is
-         resolved.  Note that svn_wc__db_base_add_not_present_node()
-         explicitly adds the node into the parent's node database. */
-
-      SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
-                                                   db->new_repos_relpath,
-                                                   eb->repos_root,
-                                                   eb->repos_uuid,
-                                                   *eb->target_revision,
-                                                   svn_node_file,
-                                                   NULL, NULL,
-                                                   pool));
+             The only thing we can do is add a not-present node, to allow
+             a future update to bring in the new files when the problem is
+             resolved.  Note that svn_wc__db_base_add_not_present_node()
+             explicitly adds the node into the parent's node database. */
 
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
-      db->skip_this = TRUE;
-      db->already_notified = TRUE;
+          svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, db->name),
+                        svn_node_kind_to_word(svn_node_dir));
+        }
+      else
+        {
+          /* We found a file external occupating the place we need in BASE.
 
-      do_notification(eb, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_update_skip_obstruction, pool);
+            We can't add a not-present node in this case as that would overwrite
+            the file external. Luckily the file external itself stops us from
+            forgetting a child of this parent directory like an obstructing
+            working copy would.
 
-      return SVN_NO_ERROR;
-    }
-  else if (status == svn_wc__db_status_normal
-           && (wc_kind == svn_node_file
-               || wc_kind == svn_node_symlink))
-    {
-      /* We found a file external occupating the place we need in BASE.
-
-         We can't add a not-present node in this case as that would overwrite
-         the file external. Luckily the file external itself stops us from
-         forgetting a child of this parent directory like an obstructing
-         working copy would.
-
-         The reason we get here is that the adm crawler doesn't report
-         file externals.
-      */
+            The reason we get here is that the adm crawler doesn't report
+            file externals.
+          */
+          SVN_ERR_ASSERT(wc_kind == svn_node_file
+                         || wc_kind == svn_node_symlink);
+        }
 
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
+      SVN_ERR(remember_skipped_tree(eb, db->local_abspath, scratch_pool));
       db->skip_this = TRUE;
       db->already_notified = TRUE;
 
-      do_notification(eb, db->local_abspath, svn_node_file,
-                      svn_wc_notify_update_skip_obstruction, pool);
+      do_notification(eb, db->local_abspath, wc_kind,
+                      svn_wc_notify_update_skip_obstruction, scratch_pool);
+
+      svn_pool_destroy(scratch_pool);
 
       return SVN_NO_ERROR;
     }
-  else if (wc_kind == svn_node_unknown)
-    versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
   else
     versioned_locally_and_present = IS_NODE_PRESENT(status);
 
@@ -2120,7 +2127,7 @@ add_directory(const char *path,
                                                       eb->db,
                                                       db->local_abspath,
                                                       tree_conflict,
-                                                      db->pool, db->pool));
+                                                      db->pool, scratch_pool));
 
           tree_conflict = svn_wc__conflict_skel_create(db->pool);
 
@@ -2129,7 +2136,7 @@ add_directory(const char *path,
                                         eb->db, db->local_abspath,
                                         reason, svn_wc_conflict_action_replace,
                                         NULL,
-                                        db->pool, db->pool));
+                                        db->pool, scratch_pool));
 
           /* And now stop checking for conflicts here and just perform
              a shadowed update */
@@ -2140,7 +2147,8 @@ add_directory(const char *path,
         }
       else
         SVN_ERR(node_already_conflicted(&conflicted, &conflict_ignored,
-                                        eb->db, db->local_abspath, pool));
+                                        eb->db, db->local_abspath,
+                                        scratch_pool));
     }
 
   /* Now the "usual" behaviour if already conflicted. Skip it. */
@@ -2163,18 +2171,13 @@ add_directory(const char *path,
          Note that we can safely assume that no present base node exists,
          because then we would not have received an add_directory.
        */
-      SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
-                                                   db->new_repos_relpath,
-                                                   eb->repos_root,
-                                                   eb->repos_uuid,
-                                                   *eb->target_revision,
-                                                   svn_node_dir,
-                                                   NULL, NULL,
-                                                   pool));
+      svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, db->name),
+                    svn_node_kind_to_word(svn_node_dir));
 
-      /* ### TODO: Also print victim_path in the skip msg. */
       do_notification(eb, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_skip_conflicted, pool);
+                      svn_wc_notify_skip_conflicted, scratch_pool);
+
+      svn_pool_destroy(scratch_pool);
       return SVN_NO_ERROR;
     }
   else if (conflict_ignored)
@@ -2207,7 +2210,7 @@ add_directory(const char *path,
         SVN_ERR(svn_wc__db_scan_addition(&add_status, NULL, NULL, NULL, NULL,
                                          NULL, NULL, NULL, NULL,
                                          eb->db, db->local_abspath,
-                                         pool, pool));
+                                         scratch_pool, scratch_pool));
 
 
       /* Is there *something* that is not a dir? */
@@ -2230,7 +2233,7 @@ add_directory(const char *path,
                                       db->local_abspath,
                                       status, FALSE, svn_node_none,
                                       svn_wc_conflict_action_add,
-                                      pool, pool));
+                                      db->pool, scratch_pool));
         }
 
       if (tree_conflict == NULL)
@@ -2258,7 +2261,7 @@ add_directory(const char *path,
                                         eb->db, db->local_abspath,
                                         svn_wc_conflict_reason_unversioned,
                                         svn_wc_conflict_action_add, NULL,
-                                        db->pool, pool));
+                                        db->pool, scratch_pool));
           db->edit_conflict = tree_conflict;
         }
     }
@@ -2269,7 +2272,7 @@ add_directory(const char *path,
                               db->new_repos_relpath,
                               wc_kind,
                               svn_node_dir,
-                              db->pool, pool));
+                              db->pool, scratch_pool));
 
   SVN_ERR(svn_wc__db_base_add_incomplete_directory(
                                      eb->db, db->local_abspath,
@@ -2282,12 +2285,12 @@ add_directory(const char *path,
                                      (! db->shadowed
                                       && status == svn_wc__db_status_added),
                                      tree_conflict, NULL,
-                                     pool));
+                                     scratch_pool));
 
   /* Make sure there is a real directory at LOCAL_ABSPATH, unless we are just
      updating the DB */
   if (!db->shadowed)
-    SVN_ERR(svn_wc__ensure_directory(db->local_abspath, pool));
+    SVN_ERR(svn_wc__ensure_directory(db->local_abspath, scratch_pool));
 
   if (tree_conflict != NULL)
     {
@@ -2299,11 +2302,11 @@ add_directory(const char *path,
                                                  eb->conflict_baton,
                                                  eb->cancel_func,
                                                  eb->cancel_baton,
-                                                 pool));
+                                                 scratch_pool));
 
       db->already_notified = TRUE;
       do_notification(eb, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_tree_conflict, pool);
+                      svn_wc_notify_tree_conflict, scratch_pool);
     }
 
 
@@ -2325,9 +2328,12 @@ add_directory(const char *path,
 
       db->already_notified = TRUE;
 
-      do_notification(eb, db->local_abspath, svn_node_dir, action, pool);
+      do_notification(eb, db->local_abspath, svn_node_dir, action,
+                      scratch_pool);
     }
 
+  svn_pool_destroy(scratch_pool);
+
   return SVN_NO_ERROR;
 }
 
@@ -2767,7 +2773,7 @@ close_directory(void *dir_baton,
       }
   }
 
-  if (apr_hash_count(db->not_present_files))
+  if (apr_hash_count(db->not_present_nodes))
     {
       apr_hash_index_t *hi;
       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -2777,12 +2783,14 @@ close_directory(void *dir_baton,
          transaction, but I can't even trigger it.  I've tried
          ra_local, ra_svn, ra_neon, ra_serf and they all call
          close_file before close_dir. */
-      for (hi = apr_hash_first(scratch_pool, db->not_present_files);
+      for (hi = apr_hash_first(scratch_pool, db->not_present_nodes);
            hi;
            hi = apr_hash_next(hi))
         {
           const char *child = svn__apr_hash_index_key(hi);
           const char *child_abspath, *child_relpath;
+          svn_node_kind_t kind = svn_node_kind_from_word(
+                                      svn__apr_hash_index_val(hi));
 
           svn_pool_clear(iterpool);
 
@@ -2795,7 +2803,7 @@ close_directory(void *dir_baton,
                                                        eb->repos_root,
                                                        eb->repos_uuid,
                                                        *eb->target_revision,
-                                                       svn_node_file,
+                                                       kind,
                                                        NULL, NULL,
                                                        iterpool));
         }
@@ -2917,6 +2925,9 @@ close_directory(void *dir_baton,
                          eb->cancel_func, eb->cancel_baton,
                          scratch_pool));
 
+  if (db->parent_baton)
+    svn_hash_sets(db->parent_baton->not_present_nodes, db->name, NULL);
+
   if (conflict_skel && eb->conflict_func)
     SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath,
                                              conflict_skel,
@@ -3136,13 +3147,13 @@ add_file(const char *path,
   struct dir_baton *pb = parent_baton;
   struct edit_baton *eb = pb->edit_baton;
   struct file_baton *fb;
-  svn_node_kind_t kind = svn_node_none;
-  svn_node_kind_t wc_kind = svn_node_unknown;
-  svn_wc__db_status_t status = svn_wc__db_status_normal;
+  svn_node_kind_t kind;
+  svn_node_kind_t wc_kind;
+  svn_wc__db_status_t status;
   apr_pool_t *scratch_pool;
-  svn_boolean_t conflicted = FALSE;
+  svn_boolean_t conflicted;
   svn_boolean_t conflict_ignored = FALSE;
-  svn_boolean_t versioned_locally_and_present = FALSE;
+  svn_boolean_t versioned_locally_and_present;
   svn_skel_t *tree_conflict = NULL;
   svn_error_t *err = SVN_NO_ERROR;
 
@@ -3182,6 +3193,13 @@ add_file(const char *path,
                                 eb->db, fb->local_abspath,
                                 scratch_pool, scratch_pool);
     }
+  else
+    {
+      kind =  svn_node_none;
+      status = svn_wc__db_status_not_present;
+      wc_kind = svn_node_unknown;
+      conflicted = FALSE;
+    }
 
   if (err)
     {
@@ -3194,58 +3212,53 @@ add_file(const char *path,
 
       versioned_locally_and_present = FALSE;
     }
-  else if (wc_kind == svn_node_dir
-           && status == svn_wc__db_status_normal)
+  else if (status == svn_wc__db_status_normal && wc_kind == svn_node_unknown)
     {
-      /* !! We found the root of a separate working copy obstructing the wc !!
-
-         If the directory would be part of our own working copy then
-         we wouldn't have been called as an add_file().
+      SVN_ERR_ASSERT(conflicted);
+      versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
+    }
+  else if (status == svn_wc__db_status_normal)
+    {
+      if (wc_kind == svn_node_dir)
+        {
+          /* !! We found the root of a working copy obstructing the wc !!
 
-         The only thing we can do is add a not-present node, to allow
-         a future update to bring in the new files when the problem is
-         resolved. */
-      svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
-                    (void *)1);
+             If the directory would be part of our own working copy then
+             we wouldn't have been called as an add_file().
 
-      SVN_ERR(remember_skipped_tree(eb, fb->local_abspath, pool));
-      fb->skip_this = TRUE;
-      fb->already_notified = TRUE;
+             The only thing we can do is add a not-present node, to allow
+             a future update to bring in the new files when the problem is
+             resolved. */
+          svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
+                        svn_node_kind_to_word(svn_node_file));
+        }
+      else
+        {
+          /* We found a file external occupating the place we need in BASE.
 
-      do_notification(eb, fb->local_abspath, svn_node_file,
-                      svn_wc_notify_update_skip_obstruction, scratch_pool);
+             We can't add a not-present node in this case as that would overwrite
+             the file external. Luckily the file external itself stops us from
+             forgetting a child of this parent directory like an obstructing
+             working copy would.
 
-      svn_pool_destroy(scratch_pool);
+             The reason we get here is that the adm crawler doesn't report
+             file externals.
+           */
+          SVN_ERR_ASSERT(wc_kind == svn_node_file
+                         || wc_kind == svn_node_symlink);
+        }
 
-      return SVN_NO_ERROR;
-    }
-  else if (status == svn_wc__db_status_normal
-           && (wc_kind == svn_node_file
-               || wc_kind == svn_node_symlink))
-    {
-      /* We found a file external occupating the place we need in BASE.
-
-         We can't add a not-present node in this case as that would overwrite
-         the file external. Luckily the file external itself stops us from
-         forgetting a child of this parent directory like an obstructing
-         working copy would.
-
-         The reason we get here is that the adm crawler doesn't report
-         file externals.
-      */
       SVN_ERR(remember_skipped_tree(eb, fb->local_abspath, pool));
       fb->skip_this = TRUE;
       fb->already_notified = TRUE;
 
-      do_notification(eb, fb->local_abspath, svn_node_file,
+      do_notification(eb, fb->local_abspath, wc_kind,
                       svn_wc_notify_update_skip_obstruction, scratch_pool);
 
       svn_pool_destroy(scratch_pool);
 
       return SVN_NO_ERROR;
     }
-  else if (wc_kind == svn_node_unknown)
-    versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
   else
     versioned_locally_and_present = IS_NODE_PRESENT(status);
 
@@ -3313,10 +3326,10 @@ add_file(const char *path,
          Note that we can safely assume that no present base node exists,
          because then we would not have received an add_file.
        */
-      svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
-                    (void *)1);
+      svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
+                    svn_node_kind_to_word(svn_node_file));
 
-      do_notification(eb, fb->local_abspath, svn_node_unknown,
+      do_notification(eb, fb->local_abspath, svn_node_file,
                       svn_wc_notify_skip_conflicted, scratch_pool);
 
       svn_pool_destroy(scratch_pool);
@@ -3418,8 +3431,8 @@ add_file(const char *path,
       || *eb->target_basename == '\0'
       || (strcmp(fb->local_abspath, eb->target_abspath) != 0))
     {
-      svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
-                    (void *)1);
+      svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
+                    svn_node_kind_to_word(svn_node_file));
     }
 
   if (tree_conflict != NULL)
@@ -4619,7 +4632,7 @@ close_file(void *file_baton,
 
   /* Deal with the WORKING tree, based on updates to the BASE tree.  */
 
-  svn_hash_sets(fb->dir_baton->not_present_files, fb->name, NULL);
+  svn_hash_sets(fb->dir_baton->not_present_nodes, fb->name, NULL);
 
   /* Send a notification to the callback function.  (Skip notifications
      about files which were already notified for another reason.) */