Author: rhuijben
Date: Thu Mar 31 11:47:11 2011
New Revision: 1087258

URL: http://svn.apache.org/viewvc?rev=1087258&view=rev
Log:
In preparation for a major commit processing cleanup add a wc_db helper
function determines whether a node is replaced in a few ways.

* subversion/libsvn_wc/wc_db.c
  (check_replace_baton): New struct.
  (check_replace_txn): New function.
  (svn_wc__db_node_check_replace): New function.

* subversion/libsvn_wc/wc_db.h
  (svn_wc__db_node_check_replace): New function.

Modified:
    subversion/trunk/subversion/libsvn_wc/wc_db.c
    subversion/trunk/subversion/libsvn_wc/wc_db.h

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1087258&r1=1087257&r2=1087258&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Thu Mar 31 11:47:11 2011
@@ -5806,6 +5806,183 @@ svn_wc__db_read_replaced_children(const 
   return SVN_NO_ERROR;
 }
 
+/* Baton for check_replace_txn */
+struct check_replace_baton
+{
+  svn_boolean_t *is_replace_root;
+  svn_boolean_t *base_replace;
+  svn_boolean_t is_replace;
+};
+
+/* Helper for svn_wc__db_node_check_replace. Implements
+   svn_wc__db_txn_callback_t */
+static svn_error_t *
+check_replace_txn(void *baton,
+                  svn_wc__db_wcroot_t *wcroot,
+                  const char *local_relpath,
+                  apr_pool_t *scratch_pool)
+{
+  struct check_replace_baton *crb = baton;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  apr_int64_t replaced_op_depth;
+  svn_wc__db_status_t replaced_status;
+
+  /* Our caller initialized the output values in crb to FALSE */
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_NODE_INFO));
+
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+                             svn_sqlite__reset(stmt),
+                             _("The node '%s' was not found."),
+                             path_for_error_message(wcroot, local_relpath,
+                                                    scratch_pool));
+
+  {
+    svn_wc__db_status_t status;
+
+    status = svn_sqlite__column_token(stmt, 3, presence_map);
+
+    if (status != svn_wc__db_status_normal)
+      return svn_error_return(svn_sqlite__reset(stmt));
+  }
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (!have_row)
+    return svn_error_return(svn_sqlite__reset(stmt));
+
+  replaced_status = svn_sqlite__column_token(stmt, 3, presence_map);
+
+  /* If the layer below the add describes a not present or a deleted node,
+     this is not a replacement. Deleted can only occur if an ancestor is
+     the delete root. */
+  if (replaced_status != svn_wc__db_status_not_present
+      && replaced_status != svn_wc__db_status_excluded
+      && replaced_status != svn_wc__db_status_absent
+      && replaced_status != svn_wc__db_status_base_deleted)
+    crb->is_replace = TRUE;
+
+  replaced_op_depth = svn_sqlite__column_int64(stmt, 0);
+
+  SVN_DBG(("Found replaced depth %d for %s\n", (int)replaced_op_depth, 
local_relpath));
+
+  if (crb->base_replace)
+    {
+      apr_int64_t op_depth = svn_sqlite__column_int64(stmt, 0);
+
+      while (op_depth != 0 && have_row)
+        {
+          SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+          if (have_row)
+            op_depth = svn_sqlite__column_int64(stmt, 0);
+        }
+
+      if (have_row && op_depth == 0)
+        {
+          svn_wc__db_status_t base_status;
+
+          base_status = svn_sqlite__column_token(stmt, 3, presence_map);
+                                           
+          *crb->base_replace = (base_status != svn_wc__db_status_not_present);
+        }
+    }
+
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  if (!crb->is_replace_root || !crb->is_replace)
+    return SVN_NO_ERROR;
+
+  SVN_DBG(("Checking op_depths for %s\n", local_relpath));
+
+  if (replaced_status != svn_wc__db_status_base_deleted)
+    {
+      apr_int64_t parent_op_depth;
+    
+      /* Check the current op-depth of the parent to see if we are a 
replacement
+         root */
+      SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id,
+                                svn_relpath_dirname(local_relpath,
+                                                    scratch_pool)));
+    
+      SVN_ERR(svn_sqlite__step_row(stmt)); /* Parent must exist as 'normal' */
+    
+      parent_op_depth = svn_sqlite__column_int64(stmt, 0);
+    
+      if (parent_op_depth >= replaced_op_depth)
+        {
+          /* Did we replace inside our directory? */
+
+          *crb->is_replace_root = (parent_op_depth == replaced_op_depth);
+          SVN_ERR(svn_sqlite__reset(stmt));
+          return SVN_NO_ERROR;
+        }
+    
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    
+      if (have_row)
+        parent_op_depth = svn_sqlite__column_int64(stmt, 0);
+    
+      SVN_ERR(svn_sqlite__reset(stmt));
+    
+      if (!have_row)
+        *crb->is_replace_root = TRUE; /* Parent is no replacement */
+      else if (parent_op_depth < replaced_op_depth)
+        *crb->is_replace_root = TRUE; /* Parent replaces a lower layer */
+      /*else // No replacement root */
+  }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_node_check_replace(svn_boolean_t *is_replace_root,
+                              svn_boolean_t *base_replace,
+                              svn_boolean_t *is_replace,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+  struct check_replace_baton crb;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                                             local_abspath,
+                                             scratch_pool, scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  if (is_replace_root)
+    *is_replace_root = FALSE;
+  if (is_replace)
+    *is_replace = FALSE;
+  if (base_replace)
+    *base_replace = FALSE;
+
+  if (local_relpath[0] == '\0')
+    return SVN_NO_ERROR; /* Working copy root can't be replaced */
+
+  crb.is_replace_root = is_replace_root;
+  crb.base_replace = base_replace;
+  crb.is_replace = FALSE;
+
+  SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, check_replace_txn, &crb,
+                              scratch_pool));
+
+  if (is_replace)
+    *is_replace = crb.is_replace;
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_wc__db_read_children(const apr_array_header_t **children,

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1087258&r1=1087257&r2=1087258&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Thu Mar 31 11:47:11 2011
@@ -1760,6 +1760,27 @@ svn_wc__db_node_hidden(svn_boolean_t *hi
                        const char *local_abspath,
                        apr_pool_t *scratch_pool);
 
+/* Checks if a node replaces a node in a different layer. Also check if it
+   replaces a BASE (op_depth 0) node or just a node in a higher layer (a copy).
+   Finally check if this is the root of the replacement, or if the replacement
+   is initiated by the parent node.
+
+   IS_REPLACE_ROOT (if not NULL) is set to TRUE if the node is the root of a
+   replacement; otherwise to FALSE.
+
+   BASE_REPLACE (if not NULL) is set to TRUE if the node directly or indirectly
+   replaces a node in the BASE tree; otherwise to FALSE.
+
+   IS_REPLACE (if not NULL) is set to TRUE if the node directly replaces a node
+   in a lower layer; otherwise to FALSE.
+ */
+svn_error_t *
+svn_wc__db_node_check_replace(svn_boolean_t *is_replace_root,
+                              svn_boolean_t *base_replace,
+                              svn_boolean_t *is_replace,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              apr_pool_t *scratch_pool);
 
 /* ### changelists. return an array, or an iterator interface? how big
    ### are these things? are we okay with an in-memory array? examine other


Reply via email to