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/06/04 13:14:00 UTC

svn commit: r951368 - in /subversion/trunk/subversion/libsvn_wc: wc-queries.sql wc_db.c wc_db.h

Author: gstein
Date: Fri Jun  4 11:14:00 2010
New Revision: 951368

URL: http://svn.apache.org/viewvc?rev=951368&view=rev
Log:
Implement the application of old-style propfiles against the database
during an upgrade process. (tho this code isn't really tested yet)

* subversion/libsvn_wc/wc_db.h:
  (svn_wc__db_upgrade_apply_props): add some sketchy docco

* subversion/libsvn_wc/wc_db.c:
  (prop_upgrade_trees): helper function to find the available trees,
    WORKING presence, and WC_ID values for a props upgrade.
  (struct set_props_baton): replace PDH with WC_ID
  (set_props_txn): use WC_ID member, as appropriate
  (svn_wc__db_op_set_props): assert abspath input. adjust logic to store a
    WC_ID into the baton, rather than a PDH.
  (svn_wc__db_upgrade_apply_props): implement this sucker

* subversion/libsvn_wc/wc-queries.sql:
  (STMT_PLAN_PROP_UPGRADE): new query

Modified:
    subversion/trunk/subversion/libsvn_wc/wc-queries.sql
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h

Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=951368&r1=951367&r2=951368&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Fri Jun  4 11:14:00 2010
@@ -530,6 +530,11 @@ UNION
 SELECT local_relpath FROM WORKING_NODE
 WHERE kind = 'file';
 
+-- STMT_PLAN_PROP_UPGRADE
+SELECT 0, null, wc_id FROM BASE_NODE WHERE local_relpath = ?1
+UNION
+SELECT 1, presence, wc_id FROM WORKING_NODE WHERE local_relpath = ?1;
+
 
 /* ------------------------------------------------------------------------- */
 

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=951368&r1=951367&r2=951368&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Fri Jun  4 11:14:00 2010
@@ -967,6 +967,70 @@ which_trees_exist(svn_boolean_t *base_ex
 }
 
 
+/* Determine which trees' nodes exist for a given LOCAL_RELPATH in the
+   specified SDB.
+
+   Note: this is VERY similar to the above which_trees_exist() except that
+   we return a WC_ID and verify some additional constraints.  */
+static svn_error_t *
+prop_upgrade_trees(svn_boolean_t *base_exists,
+                   svn_boolean_t *working_exists,
+                   svn_wc__db_status_t *work_presence,
+                   apr_int64_t *wc_id,
+                   svn_sqlite__db_t *sdb,
+                   const char *local_relpath)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  *base_exists = FALSE;
+  *working_exists = FALSE;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_PLAN_PROP_UPGRADE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "s", local_relpath));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  /* During a property upgrade, there better be a row corresponding to
+     the provided LOCAL_RELPATH. We shouldn't even be here without a
+     query for available rows.  */
+  SVN_ERR_ASSERT(have_row);
+
+  /* Use the first column to detect which table this row came from.  */
+  if (svn_sqlite__column_int(stmt, 0))
+    {
+      *working_exists = TRUE;  /* value == 1  */
+      *work_presence = svn_sqlite__column_token(stmt, 1, presence_map);
+    }
+  else
+    {
+      *base_exists = TRUE;  /* value == 0  */
+    }
+
+  /* Return the WC_ID that was assigned.  */
+  *wc_id = svn_sqlite__column_int64(stmt, 2);
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    {
+      /* If both rows, then both tables.  */
+      *base_exists = TRUE;
+      *working_exists = TRUE;
+
+      /* If the second row came from WORKING_NODE, then we should also
+         fetch the 'presence' column value.  */
+      if (svn_sqlite__column_int(stmt, 0))
+        *work_presence = svn_sqlite__column_token(stmt, 1, presence_map);
+
+      /* During an upgrade, there should be just one working copy, so both
+         rows should refer to the same value.  */
+      SVN_ERR_ASSERT(*wc_id == svn_sqlite__column_int64(stmt, 2));
+    }
+
+  return svn_error_return(svn_sqlite__reset(stmt));
+}
+
+
 /* */
 static svn_error_t *
 create_db(svn_sqlite__db_t **sdb,
@@ -2857,8 +2921,8 @@ struct set_props_baton
 {
   apr_hash_t *props;
 
+  apr_int64_t wc_id;
   const char *local_relpath;
-  svn_wc__db_pdh_t *pdh;
 
   const svn_skel_t *conflict;
   const svn_skel_t *work_items;
@@ -2884,26 +2948,21 @@ set_props_txn(void *baton, svn_sqlite__d
   SVN_ERR(add_work_items(db, spb->work_items, scratch_pool));
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_UPDATE_ACTUAL_PROPS));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", spb->pdh->wcroot->wc_id,
-                            spb->local_relpath));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", spb->wc_id, spb->local_relpath));
   SVN_ERR(svn_sqlite__bind_properties(stmt, 3, spb->props, scratch_pool));
   SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
 
   if (affected_rows == 1)
     return SVN_NO_ERROR; /* We are done */
 
-  /* We have to insert a row in actual */
+  /* We have to insert a row in ACTUAL */
 
   SVN_ERR(svn_sqlite__get_statement(&stmt, db, STMT_INSERT_ACTUAL_PROPS));
-
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", spb->pdh->wcroot->wc_id,
-                            spb->local_relpath));
-
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", spb->wc_id, spb->local_relpath));
   if (*spb->local_relpath != '\0')
     SVN_ERR(svn_sqlite__bind_text(stmt, 3,
                                   svn_relpath_dirname(spb->local_relpath,
                                                       scratch_pool)));
-
   SVN_ERR(svn_sqlite__bind_properties(stmt, 4, spb->props, scratch_pool));
   return svn_error_return(svn_sqlite__step_done(stmt));
 }
@@ -2917,17 +2976,22 @@ svn_wc__db_op_set_props(svn_wc__db_t *db
                         apr_pool_t *scratch_pool)
 {
   struct set_props_baton spb;
+  svn_wc__db_pdh_t *pdh;
 
-  spb.props = props;
-  spb.conflict = conflict;
-  spb.work_items = work_items;
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&spb.pdh, &spb.local_relpath, db,
+  SVN_ERR(svn_wc__db_pdh_parse_local_abspath(&pdh, &spb.local_relpath, db,
                               local_abspath, svn_sqlite__mode_readwrite,
                               scratch_pool, scratch_pool));
+  VERIFY_USABLE_PDH(pdh);
+
+  spb.props = props;
+  spb.wc_id = pdh->wcroot->wc_id;
+  spb.conflict = conflict;
+  spb.work_items = work_items;
 
   return svn_error_return(
-            svn_sqlite__with_transaction(spb.pdh->wcroot->sdb,
+            svn_sqlite__with_transaction(pdh->wcroot->sdb,
                                          set_props_txn,
                                          &spb,
                                          scratch_pool));
@@ -5803,7 +5867,12 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
                                int original_format,
                                apr_pool_t *scratch_pool)
 {
-  NOT_IMPLEMENTED();
+  svn_boolean_t have_base;
+  svn_boolean_t have_work;
+  svn_wc__db_status_t work_presence;
+  apr_int64_t wc_id;
+  svn_sqlite__stmt_t *stmt;
+  int affected_rows;
 
   /* ### working_props: use set_props_txn.
      ### if working_props == NULL, then skip. what if they equal the
@@ -5813,9 +5882,10 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
      ###
      ### revert only goes into BASE. (and WORKING better be there!)
 
-     Prior to 1.4.0, REVERT_PROPS did not exist. If a file was deleted,
-     then a copy (with props) could not replace the deletion. An addition
-     *could* be performed, but that would never bring its own props.
+     Prior to 1.4.0 (ORIGINAL_FORMAT < 8), REVERT_PROPS did not exist. If a
+     file was deleted, then a copy (potentially with props) was disallowed
+     and could not replace the deletion. An addition *could* be performed,
+     but that would never bring its own props.
 
      1.4.0 through 1.4.5 created the concept of REVERT_PROPS, but had a
      bug in svn_wc_add_repos_file2() whereby a copy-with-props did NOT
@@ -5830,6 +5900,80 @@ svn_wc__db_upgrade_apply_props(svn_sqlit
      We will use ORIGINAL_FORMAT and SVN_WC__NO_REVERT_FILES to determine
      the handling of our inputs, relative to the state of this node.
   */
+
+  /* Collect information about this node.  */
+  SVN_ERR(prop_upgrade_trees(&have_base, &have_work, &work_presence, &wc_id,
+                             sdb, local_relpath));
+
+  /* Detect the buggy scenario described above. We cannot upgrade this
+     working copy if we have no idea where BASE_PROPS should go.  */
+  if (original_format > SVN_WC__NO_REVERT_FILES
+      && revert_props == NULL
+      && have_work
+      && work_presence == svn_wc__db_status_normal)
+    {
+      /* There should be REVERT_PROPS, so it appears that we just ran into
+         the described bug. Sigh.  */
+      return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
+                               _("The properties of '%s' are in an "
+                                 "indeterminate state and cannot be "
+                                 "upgraded. See issue #2530."),
+                               local_relpath);
+    }
+
+  if (have_base)
+    {
+      apr_hash_t *props = revert_props ? revert_props : base_props;
+
+      SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_UPDATE_BASE_PROPS));
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+      SVN_ERR(svn_sqlite__bind_properties(stmt, 3, props, scratch_pool));
+      SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+      /* ### should we provide a nicer error message?  */
+      SVN_ERR_ASSERT(affected_rows == 1);
+    }
+
+  if (have_work)
+    {
+      /* WORKING_NODE has very limited 'presence' values.  */
+      SVN_ERR_ASSERT(work_presence == svn_wc__db_status_normal
+                     || work_presence == svn_wc__db_status_not_present
+                     || work_presence == svn_wc__db_status_base_deleted
+                     || work_presence == svn_wc__db_status_incomplete);
+
+      /* Do we have a replaced node? It has properties: an empty set for
+         adds, and a non-empty set for copies/moves.  */
+      if (work_presence == svn_wc__db_status_normal
+          && original_format > SVN_WC__NO_REVERT_FILES)
+        {
+          SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                            STMT_UPDATE_WORKING_PROPS));
+          SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, local_relpath));
+          SVN_ERR(svn_sqlite__bind_properties(stmt, 3, revert_props,
+                                              scratch_pool));
+          SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
+
+          /* ### should we provide a nicer error message?  */
+          SVN_ERR_ASSERT(affected_rows == 1);
+        }
+      /* else other states should have no properties.  */
+      /* ### should we insert empty props for <= SVN_WC__NO_REVERT_FILES?  */
+    }
+
+  /* If there are WORKING_PROPS, then they always go into ACTUAL_NODE.  */
+  if (working_props != NULL)
+    {
+      struct set_props_baton spb = { 0 };
+
+      spb.props = working_props;
+      spb.wc_id = wc_id;
+      spb.local_relpath = local_relpath;
+      /* NULL for .conflict and .work_items  */
+      SVN_ERR(set_props_txn(&spb, sdb, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=951368&r1=951367&r2=951368&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Fri Jun  4 11:14:00 2010
@@ -2015,6 +2015,15 @@ svn_wc__db_upgrade_apply_dav_cache(svn_s
                                    apr_pool_t *scratch_pool);
 
 
+/* ### need much more docco
+
+   ### this function should be called within a sqlite transaction. it makes
+   ### assumptions around this fact.
+
+   Apply the various sets of properties to the database nodes based on
+   their existence/presence, the current state of the node, and the original
+   format of the working copy which provided these property sets.
+*/
 svn_error_t *
 svn_wc__db_upgrade_apply_props(svn_sqlite__db_t *sdb,
                                const char *local_relpath,