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 2012/07/04 18:27:48 UTC

svn commit: r1357333 - in /subversion/trunk/subversion/libsvn_wc: conflicts.c conflicts.h wc_db.c

Author: rhuijben
Date: Wed Jul  4 16:27:47 2012
New Revision: 1357333

URL: http://svn.apache.org/viewvc?rev=1357333&view=rev
Log:
Add support for resolving specific conflicts when using the currently still
disabled conflict-skel storage.

* subversion/libsvn_wc/conflicts.c
  (svn_wc__conflict_skel_resolve): New function.

* subversion/libsvn_wc/conflicts.h
  (svn_wc__conflict_skel_resolve): New function.

* subversion/libsvn_wc/wc_db.c
  (op_mark_resolved_baton): Add db.
  (db_op_mark_resolved): Add implementation for conflict skel storage. Return
    an error when operating on non-existing paths.

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

Modified: subversion/trunk/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/conflicts.c?rev=1357333&r1=1357332&r2=1357333&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_wc/conflicts.c Wed Jul  4 16:27:47 2012
@@ -566,6 +566,91 @@ svn_wc__conflict_skel_add_tree_conflict(
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__conflict_skel_resolve(svn_boolean_t *completely_resolved,
+                              svn_skel_t *conflict_skel,
+                              svn_wc__db_t *db,
+                              const char *wri_abspath,
+                              svn_boolean_t resolve_text,
+                              const char *resolve_prop,
+                              svn_boolean_t resolve_tree,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  svn_skel_t *op;
+  svn_skel_t **pconflict;
+  SVN_ERR(conflict__get_operation(&op, conflict_skel));
+
+  if (!op)
+    return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+                            _("Not a completed conflict skel"));
+
+  /* We are going to drop items from a linked list. Instead of keeping
+     a pointer to the item we want to drop we store a pointer to the
+     pointer of what we may drop, to allow setting it to the next item. */
+
+  pconflict = &(conflict_skel->children->next->children);
+  while (*pconflict)
+    {
+      svn_skel_t *c = (*pconflict)->children;
+
+      if (resolve_text
+          && svn_skel__matches_atom(c, SVN_WC__CONFLICT_KIND_TEXT))
+        {
+          /* Remove the text conflict from the linked list */
+          *pconflict = (*pconflict)->next;
+          continue;
+        }
+      else if (resolve_prop
+               && svn_skel__matches_atom(c, SVN_WC__CONFLICT_KIND_PROP))
+        {
+          svn_skel_t **ppropnames = &(c->next->next->children);
+
+          if (resolve_prop[0] == '\0')
+            *ppropnames = NULL; /* remove all conflicted property names */
+          else
+            while (*ppropnames)
+              {
+                if (svn_skel__matches_atom(*ppropnames, resolve_prop))
+                  {
+                    *ppropnames = (*ppropnames)->next;
+                    break;
+                  }
+                ppropnames = &((*ppropnames)->next);
+              }
+
+          /* If no conflicted property names left */
+          if (!c->next->next->children)
+            {
+              /* Remove the propery conflict skel from the linked list */
+             *pconflict = (*pconflict)->next;
+             continue;
+            }
+        }
+      else if (resolve_tree
+               && svn_skel__matches_atom(c, SVN_WC__CONFLICT_KIND_TREE))
+        {
+          /* Remove the tree conflict from the linked list */
+          *pconflict = (*pconflict)->next;
+          continue;
+        }
+
+      pconflict = &((*pconflict)->next);
+    }
+
+  if (completely_resolved)
+    {
+      /* Nice, we can just call the complete function */
+      svn_boolean_t complete_conflict;
+      SVN_ERR(svn_wc__conflict_skel_is_complete(&complete_conflict,
+                                                conflict_skel));
+
+      *completely_resolved = !complete_conflict;
+    }
+  return SVN_NO_ERROR;
+}
+
+
 /* A map for svn_wc_operation_t values. */
 static const svn_token_map_t operation_map[] =
 {

Modified: subversion/trunk/subversion/libsvn_wc/conflicts.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/conflicts.h?rev=1357333&r1=1357332&r2=1357333&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/conflicts.h (original)
+++ subversion/trunk/subversion/libsvn_wc/conflicts.h Wed Jul  4 16:27:47 2012
@@ -212,6 +212,42 @@ svn_wc__conflict_skel_add_tree_conflict(
                                         apr_pool_t *result_pool,
                                         apr_pool_t *scratch_pool);
 
+/* Allows resolving specific conflicts stored in CONFLICT_SKEL.
+
+   When RESOLVE_TEXT is TRUE and CONFLICT_SKEL contains a text conflict,
+   resolve/remove the text conflict in CONFLICT_SKEL.
+
+   When RESOLVE_PROP is "" and CONFLICT_SKEL contains a property conflict,
+   resolve/remove all property conflicts in CONFLICT_SKEL.
+
+   When RESOLVE_PROP is not NULL and not "", remove the property conflict on
+   the property RESOLVE_PROP in CONFLICT_SKEL. When RESOLVE_PROP was the last
+   property in CONFLICT_SKEL remove the property conflict info from
+   CONFLICT_SKEL.
+
+   When RESOLVE_TREE is TRUE and CONFLICT_SKEL contains a tree conflict,
+   resolve/remove the tree conflict in CONFLICT_SKEL.
+
+   If COMPLETELY_RESOLVED is not NULL, then set *COMPLETELY_RESOLVED to TRUE,
+   when no conflict registration is left in CONFLICT_SKEL after editting,
+   otherwise to FALSE.
+
+   Allocate data stored in the skel in RESULT_POOL.
+
+   This functions edits CONFLICT_SKEL. New skels might be created in
+   RESULT_POOL. Temporary allocations will use SCRATCH_POOL.
+ */
+/* ### db, wri_abspath is currently unused. Remove? */
+svn_error_t *
+svn_wc__conflict_skel_resolve(svn_boolean_t *completely_resolved,
+                              svn_skel_t *conflict_skel,
+                              svn_wc__db_t *db,
+                              const char *wri_abspath,
+                              svn_boolean_t resolve_text,
+                              const char *resolve_prop,
+                              svn_boolean_t resolve_tree,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
 
 /*
  * -----------------------------------------------------------

Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1357333&r1=1357332&r2=1357333&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Wed Jul  4 16:27:47 2012
@@ -5483,6 +5483,9 @@ struct op_mark_resolved_baton
   svn_boolean_t resolved_props;
   svn_boolean_t resolved_tree;
   const svn_skel_t *work_items;
+#if SVN_WC__VERSION >= SVN_WC__USES_CONFLICT_SKELS
+  svn_wc__db_t *db;
+#endif
 };
 
 /* Helper for svn_wc__db_op_mark_resolved */
@@ -5494,9 +5497,48 @@ db_op_mark_resolved(void *baton,
 {
   struct op_mark_resolved_baton *rb = baton;
   svn_sqlite__stmt_t *stmt;
-  int affected_rows;
+  svn_boolean_t have_row;
   int total_affected_rows = 0;
+#if SVN_WC__VERSION < SVN_WC__USES_CONFLICT_SKELS
+  int affected_rows;
+#else
+  svn_boolean_t have_conflict;
+  apr_size_t conflict_len;
+  const void *conflict_data;
+  svn_skel_t *conflicts;
+#endif
+
+  /* Check if we have a conflict in ACTUAL */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_ACTUAL_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (! have_row)
+    {
+      SVN_ERR(svn_sqlite__reset(stmt));
+
+      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));
+      SVN_ERR(svn_sqlite__reset(stmt));
+
+      if (have_row)
+        return SVN_NO_ERROR;
+
+      return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                               _("The node '%s' was not found."),
+                                   path_for_error_message(wcroot,
+                                                          local_relpath,
+                                                          scratch_pool));
+    }
+
+#if SVN_WC__VERSION < SVN_WC__USES_CONFLICT_SKELS
+  SVN_ERR(svn_sqlite__reset(stmt));
   if (rb->resolved_text)
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
@@ -5521,6 +5563,32 @@ db_op_mark_resolved(void *baton,
       SVN_ERR(svn_sqlite__update(&affected_rows, stmt));
       total_affected_rows += affected_rows;
     }
+#else
+  conflict_data = svn_sqlite__column_blob(stmt, 2, &conflict_len,
+                                          scratch_pool);
+  conflicts = svn_skel__parse(conflict_data, conflict_len, scratch_pool);
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  SVN_ERR(svn_wc__conflict_skel_resolve(&have_conflict, conflicts,
+                                        rb->db, wcroot->abspath,
+                                        rb->resolved_text,
+                                        rb->resolved_props ? "" : NULL,
+                                        rb->resolved_tree,
+                                        scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_UPDATE_ACTUAL_CONFLICT));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+  if (have_conflict)
+    {
+      svn_stringbuf_t *sb = svn_skel__unparse(conflicts, scratch_pool);
+
+      SVN_ERR(svn_sqlite__bind_blob(stmt, 3, sb->data, sb->len));
+    }
+
+  SVN_ERR(svn_sqlite__update(&total_affected_rows, stmt));
+#endif
 
   /* Now, remove the actual node if it doesn't have any more useful
      information.  We only need to do this if we've remove data ourselves. */
@@ -5560,6 +5628,9 @@ svn_wc__db_op_mark_resolved(svn_wc__db_t
   rb.resolved_text = resolved_text;
   rb.resolved_tree = resolved_tree;
   rb.work_items = work_items;
+#if SVN_WC__VERSION >= SVN_WC__USES_CONFLICT_SKELS
+  rb.db = db;
+#endif
 
   SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_op_mark_resolved,
                               &rb, scratch_pool));
@@ -11624,22 +11695,25 @@ get_conflict_marker_files(void *baton, s
     {
       apr_size_t len;
       const void *data = svn_sqlite__column_blob(stmt, 2, &len, scratch_pool);
-      svn_skel_t *conflicts;
+      
       const apr_array_header_t *markers;
       int i;
 
-      conflicts = svn_skel__parse(data, len, scratch_pool);
+      if (data)
+        {
+          svn_skel_t *conflicts;
+          conflicts = svn_skel__parse(data, len, scratch_pool);
 
-      /* ### ADD markers to *marker_files */
-      SVN_ERR(svn_wc__conflict_read_markers(&markers, mfb->db, wcroot->abspath,
-                                            conflicts,
-                                            result_pool, scratch_pool));
+          SVN_ERR(svn_wc__conflict_read_markers(&markers, mfb->db, wcroot->abspath,
+                                                conflicts,
+                                                result_pool, scratch_pool));
 
-      for (i = 0; markers && (i < markers->nelts); i++)
-        {
-          const char *marker_abspath = APR_ARRAY_IDX(markers, i, const char*);
+          for (i = 0; markers && (i < markers->nelts); i++)
+            {
+              const char *marker_abspath = APR_ARRAY_IDX(markers, i, const char*);
 
-          apr_hash_set(marker_files, marker_abspath, APR_HASH_KEY_STRING, "");
+              apr_hash_set(marker_files, marker_abspath, APR_HASH_KEY_STRING, "");
+            }
         }
 
       SVN_ERR(svn_sqlite__step(&have_row, stmt));