You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gs...@apache.org on 2010/04/21 10:23:57 UTC

svn commit: r936199 - in /subversion/trunk/subversion: libsvn_wc/old-and-busted.c tests/libsvn_wc/entries-compat.c

Author: gstein
Date: Wed Apr 21 08:23:56 2010
New Revision: 936199

URL: http://svn.apache.org/viewvc?rev=936199&view=rev
Log:
Revamp the old svn_wc_entry() to get entries from the cached hash of
entries, in order to follow the docstring. The (replaced) algorithm using
svn_wc__get_entry() will soon follow different pool lifetime guides which
will not use the entries cache. Thus, it would break svn_wc_entry's
guarantees about pool usage.

Add a new test to track these lifetime guarantees and baton usage.

* subversion/libsvn_wc/old-and-busted.:
  (svn_wc_entry): rebuild this similar to the logic used by 1.6.x, but
    using some wc-ng stuffs to reach access batons.

* subversion/tests/libsvn_wc/entries-compat.c:
  (M_TESTING_DATA): our new test requires a second .svn metadata area, and
    this content will be loaded.
  (make_one_db): new function comprised of the guts of create_fake_wc.
  (create_fake_wc): shift content out to make_one_db, and then use that to
    create two metadata areas for the tests.
  (test_stubs): new testing function to verify interaction of the access
    batons, the entries hash, and the svn_wc_entry() return values.
  (test_funcs): add new test

Modified:
    subversion/trunk/subversion/libsvn_wc/old-and-busted.c
    subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c

Modified: subversion/trunk/subversion/libsvn_wc/old-and-busted.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/old-and-busted.c?rev=936199&r1=936198&r2=936199&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/old-and-busted.c (original)
+++ subversion/trunk/subversion/libsvn_wc/old-and-busted.c Wed Apr 21 08:23:56 2010
@@ -1301,48 +1301,47 @@ svn_wc_entry(const svn_wc_entry_t **entr
              svn_boolean_t show_hidden,
              apr_pool_t *pool)
 {
+  svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
   const char *local_abspath;
-  svn_error_t *err;
+  svn_wc_adm_access_t *dir_access;
+  const char *entry_name;
+  apr_hash_t *entries;
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
-  err = svn_wc__get_entry(entry,
-                          svn_wc__adm_get_db(adm_access),
-                          local_abspath,
-                          TRUE /* allow_unversioned */,
-                          svn_node_unknown,
-                          FALSE /* need_parent_stub */,
-                          svn_wc_adm_access_pool(adm_access), pool);
-  if (err)
+  /* Does the provided path refer to a directory with an associated
+     access baton?  */
+  dir_access = svn_wc__adm_retrieve_internal2(db, local_abspath, pool);
+  if (dir_access == NULL)
     {
-      if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
-        {
-          /* Even though we said ALLOW_UNVERSIONED == TRUE, this error can
-             happen when the requested node is a directory, but that
-             directory is not found. We'll go ahead and return the stub.
-
-             So: fall through to clear the error.  */
-        }
-      else if (err->apr_err == SVN_ERR_WC_MISSING)
-        {
-          /* This can happen when we ask about a subdir's node, but both
-             the subdirectory and its parent are missing metadata. This
-             can happen during (say) the diff process against the repository
-             where a node *does* exist, and it looks for the same locally.
-
-             See diff_tests 36 -- diff_added_subtree()
-
-             We'll just say the entry does not exist, and fall through to
-             clear this error.  */
-          *entry = NULL;
-        }
-      else if (err->apr_err != SVN_ERR_NODE_UNEXPECTED_KIND)
-        return svn_error_return(err);
+      /* Damn. Okay. Assume the path is to a child, and let's look for
+         a baton associated with its parent.  */
 
-      /* We got the parent stub instead of the real entry. Fine.  */
-      svn_error_clear(err);
+      const char *dir_abspath;
+
+      svn_dirent_split(local_abspath, &dir_abspath, &entry_name, pool);
+
+      dir_access = svn_wc__adm_retrieve_internal2(db, dir_abspath, pool);
+    }
+  else
+    {
+      /* Woo! Got one. Look for "this dir" in the entries hash.  */
+      entry_name = "";
     }
 
+  if (dir_access == NULL)
+    {
+      /* Early exit.  */
+      *entry = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  /* Load an entries hash, and cache it into DIR_ACCESS. Go ahead and
+     fetch all entries here (optimization) since we know how to filter
+     out a "hidden" node.  */
+  SVN_ERR(svn_wc_entries_read(&entries, dir_access, TRUE, pool));
+  *entry = apr_hash_get(entries, entry_name, APR_HASH_KEY_STRING);
+
   if (!show_hidden && *entry != NULL)
     {
       svn_boolean_t hidden;

Modified: subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c?rev=936199&r1=936198&r2=936199&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/entries-compat.c Wed Apr 21 08:23:56 2010
@@ -309,23 +309,38 @@ static const char * const TESTING_DATA =
    "  null, null, null, 0, null, null, '()', 0); "
    );
 
+
+static const char * const M_TESTING_DATA = (
+   /* Load our test data.
+
+      Note: do not use named-column insertions. This allows us to test
+      the column count in the schema matches our expectation here. */
+
+   "insert into repository values (1, '" ROOT_ONE "', '" UUID_ONE "'); "
+   "insert into repository values (2, '" ROOT_TWO "', '" UUID_TWO "'); "
+   "insert into wcroot values (1, null); "
+
+   "insert into base_node values ("
+   "  1, '', 1, 'M', null, 'normal', 'dir', "
+   "  1, null, null, "
+   "  1, " TIME_1s ", '" AUTHOR_1 "', 'infinity', null, null, '()', null, 0, "
+   "  null); "
+   );
+
 WC_QUERIES_SQL_DECLARE_STATEMENTS(statements);
 
 
 static svn_error_t *
-create_fake_wc(const char *subdir, int format, apr_pool_t *scratch_pool)
+make_one_db(const char *dirpath,
+            const char * const my_statements[],
+            apr_pool_t *scratch_pool)
 {
-  const char *dirpath = svn_dirent_join_many(scratch_pool,
-                                             "fake-wc", subdir, ".svn", NULL);
   const char *dbpath = svn_dirent_join(dirpath, "wc.db", scratch_pool);
   svn_sqlite__db_t *sdb;
-  const char * const my_statements[] = {
-    statements[STMT_CREATE_SCHEMA],
-    TESTING_DATA,
-    NULL
-  };
 
+  /* Create fake-wc/SUBDIR/.svn/ for placing the metadata. */
   SVN_ERR(svn_io_make_dir_recursively(dirpath, scratch_pool));
+
   svn_error_clear(svn_io_remove_file(dbpath, scratch_pool));
   SVN_ERR(svn_sqlite__open(&sdb, dbpath, svn_sqlite__mode_rwcreate,
                            my_statements,
@@ -343,6 +358,33 @@ create_fake_wc(const char *subdir, int f
 
 
 static svn_error_t *
+create_fake_wc(const char *subdir, int format, apr_pool_t *scratch_pool)
+{
+  const char *dirpath;
+  const char * const my_statements[] = {
+    statements[STMT_CREATE_SCHEMA],
+    TESTING_DATA,
+    NULL
+  };
+  const char * const M_statements[] = {
+    statements[STMT_CREATE_SCHEMA],
+    M_TESTING_DATA,
+    NULL
+  };
+
+  dirpath = svn_dirent_join_many(scratch_pool,
+                                 "fake-wc", subdir, ".svn", NULL);
+  SVN_ERR(make_one_db(dirpath, my_statements, scratch_pool));
+
+  dirpath = svn_dirent_join_many(scratch_pool,
+                                 "fake-wc", subdir, "M", ".svn", NULL);
+  SVN_ERR(make_one_db(dirpath, M_statements, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
 create_open(svn_wc__db_t **db,
             const char **local_abspath,
             const char *subdir,
@@ -410,10 +452,85 @@ test_entries_alloc(apr_pool_t *pool)
 }
 
 
+static svn_error_t *
+test_stubs(apr_pool_t *pool)
+{
+  svn_wc__db_t *db;
+  const char *local_abspath;
+  const char *local_relpath;
+  svn_wc_adm_access_t *adm_access;
+  svn_wc_adm_access_t *subdir_access;
+  const svn_wc_entry_t *stub_entry;
+  const svn_wc_entry_t *entry;
+  const svn_wc_entry_t *test_entry;
+  apr_hash_t *entries;
+
+#undef WC_NAME
+#define WC_NAME "test_stubs"
+
+  SVN_ERR(create_open(&db, &local_abspath, WC_NAME, pool));
+
+  /* The "M" entry is a subdir. Let's ensure we can reach its stub,
+     and the actual contents.  */
+  local_relpath = svn_dirent_join_many(pool,
+                                       "fake-wc",
+                                       WC_NAME,
+                                       "M",
+                                       NULL);
+
+  SVN_ERR(svn_wc_adm_open3(&adm_access,
+                           NULL /* associated */,
+                           svn_dirent_join("fake-wc", WC_NAME, pool),
+                           FALSE /* write_lock */,
+                           0 /* levels_to_lock */,
+                           NULL /* cancel_func */,
+                           NULL /* cancel_baton */,
+                           pool));
+
+  /* Ensure we get the stub. NOTE: do this before we have associated the
+     subdir baton with ADM_ACCESS.  */
+  SVN_ERR(svn_wc_entry(&stub_entry, local_relpath, adm_access, TRUE, pool));
+  SVN_TEST_STRING_ASSERT(stub_entry->name, "M");
+
+  SVN_ERR(svn_wc_adm_open3(&subdir_access,
+                           adm_access,
+                           local_relpath,
+                           FALSE /* write_lock */,
+                           0 /* levels_to_lock */,
+                           NULL /* cancel_func */,
+                           NULL /* cancel_baton */,
+                           pool));
+
+  /* Ensure we get the real entry.  */
+  SVN_ERR(svn_wc_entry(&entry, local_relpath, subdir_access, TRUE, pool));
+  SVN_TEST_STRING_ASSERT(entry->name, "");
+
+  /* Ensure that we get the SAME entry, even using the parent baton.  */
+  SVN_ERR(svn_wc_entry(&test_entry, local_relpath, adm_access, TRUE, pool));
+  SVN_TEST_ASSERT(test_entry == entry);
+
+  /* Ensure we get the stub when reading entries with ADM_ACCESS.  */
+  SVN_ERR(svn_wc_entries_read(&entries, adm_access, TRUE /* show_hidden */,
+                              pool));
+  SVN_TEST_ASSERT(stub_entry
+                  == apr_hash_get(entries, "M", APR_HASH_KEY_STRING));
+
+  /* Ensure we get the real entry when reading entries with SUBDIR_ACCESS.  */
+  SVN_ERR(svn_wc_entries_read(&entries, subdir_access, TRUE /* show_hidden */,
+                              pool));
+  SVN_TEST_ASSERT(entry
+                  == apr_hash_get(entries, "", APR_HASH_KEY_STRING));
+
+  return SVN_NO_ERROR;
+}
+
+
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,
     SVN_TEST_PASS2(test_entries_alloc,
                    "entries are allocated in access baton"),
+    SVN_TEST_PASS2(test_stubs,
+                   "access baton mojo can return stubs"),
     SVN_TEST_NULL
   };