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/06/28 15:49:36 UTC

svn commit: r1355012 - in /subversion/trunk/subversion: libsvn_wc/conflicts.c libsvn_wc/conflicts.h tests/libsvn_wc/conflict-data-test.c

Author: rhuijben
Date: Thu Jun 28 13:49:35 2012
New Revision: 1355012

URL: http://svn.apache.org/viewvc?rev=1355012&view=rev
Log:
Implement serializing property conflicts to and from a conflict-2.0 style skel.

* subversion/libsvn_wc/conflicts.c
  (svn_wc__conflict_skel_create,
   svn_wc__conflict_skel_is_complete,
   conflict__get_conflict,
   svn_wc__conflict_skel_add_prop_conflict,
   svn_wc__conflict_read_prop_conflict): New function.

* subversion/libsvn_wc/conflicts.h
  (svn_wc__conflict_skel_new): Rename to ...
  (svn_wc__conflict_skel_create): ... this to match the common constructor
    pattern.

* subversion/tests/libsvn_wc/conflict-data-test.c
  (Header): Update filename reference and include conflicts.h
  (test_serialize_prop_conflict): New function.
  (test_funcs): Add test_serialize_prop_conflict.

Modified:
    subversion/trunk/subversion/libsvn_wc/conflicts.c
    subversion/trunk/subversion/libsvn_wc/conflicts.h
    subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c

Modified: subversion/trunk/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/conflicts.c?rev=1355012&r1=1355011&r2=1355012&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_wc/conflicts.c Thu Jun 28 13:49:35 2012
@@ -51,6 +51,269 @@
 
 #include "svn_private_config.h"
 
+/* --------------------------------------------------------------------
+ * Conflict skel management
+ */
+
+svn_skel_t *
+svn_wc__conflict_skel_create(apr_pool_t *result_pool)
+{
+  svn_skel_t *conflict_skel = svn_skel__make_empty_list(result_pool);
+
+  /* Add empty CONFLICTS list */
+  svn_skel__prepend(svn_skel__make_empty_list(result_pool), conflict_skel);
+
+  /* Add empty WHY list */
+  svn_skel__prepend(svn_skel__make_empty_list(result_pool), conflict_skel);
+
+  return conflict_skel;
+}
+
+svn_error_t *
+svn_wc__conflict_skel_is_complete(svn_boolean_t *complete,
+                                  svn_skel_t *conflict_skel,
+                                  apr_pool_t *scratch_pool)
+{
+  *complete = FALSE;
+
+  if (svn_skel__list_length(conflict_skel) < 2)
+    return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+                            _("Not a conflict skel"));
+
+  if (svn_skel__list_length(conflict_skel->children) < 2)
+    return SVN_NO_ERROR; /* WHY is not set */
+
+  if (svn_skel__list_length(conflict_skel->children->next) == 0)
+    return SVN_NO_ERROR; /* No conflict set */
+
+  *complete = TRUE;
+  return SVN_NO_ERROR;
+}
+
+/* Gets the conflict data of the specified type CONFLICT_TYPE from
+   CONFLICT_SKEL, or NULL if no such conflict is recorded */
+static svn_error_t *
+conflict__get_conflict(svn_skel_t **conflict,
+                       svn_skel_t *conflict_skel,
+                       const char *conflict_type)
+{
+  svn_skel_t *c;
+  apr_size_t len;
+  SVN_ERR_ASSERT(conflict_skel
+                 && conflict_skel->children
+                 && conflict_skel->children->next
+                 && !conflict_skel->children->next->is_atom);
+
+  len = strlen(conflict_type);
+
+  for(c = conflict_skel->children->next->children;
+      c;
+      c = c->next)
+    {
+      if (c->children->is_atom
+          && c->children->len == len
+          && memcmp(c->children->data, conflict_type, len) == 0)
+        {
+          *conflict = c;
+          return SVN_NO_ERROR;
+        }
+    }
+
+  *conflict = NULL;
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__conflict_skel_add_prop_conflict(svn_skel_t *conflict_skel,
+                                        svn_wc__db_t *db,
+                                        const char *wri_abspath,
+                                        const char *marker_abspath,
+                                        apr_hash_t *original_props,
+                                        apr_hash_t *mine_props,
+                                        apr_hash_t *their_props,
+                                        apr_hash_t *conflicted_prop_names,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool)
+{
+  svn_skel_t *prop_conflict;
+  svn_skel_t *props;
+  svn_skel_t *conflict_names;
+  svn_skel_t *markers;
+  apr_hash_index_t *hi;
+
+  SVN_ERR(conflict__get_conflict(&prop_conflict, conflict_skel,
+                                 SVN_WC__CONFLICT_KIND_PROP));
+
+  SVN_ERR_ASSERT(!prop_conflict); /* ### Use proper error? */
+
+  /* This function currently implements:
+  /* ("prop"
+      ("marker_relpath")
+      prop-conflicted_prop_names
+      original-props
+      mine-props
+      their-props)
+     NULL lists are recorded as "" */
+
+  prop_conflict = svn_skel__make_empty_list(result_pool);
+
+  if (their_props)
+    {
+      SVN_ERR(svn_skel__unparse_proplist(&props, their_props, result_pool));
+      svn_skel__prepend(props, prop_conflict);
+    }
+  else
+    svn_skel__prepend_str("", prop_conflict, result_pool); /* No their_props */
+
+  if (mine_props)
+    {
+      SVN_ERR(svn_skel__unparse_proplist(&props, mine_props, result_pool));
+      svn_skel__prepend(props, prop_conflict);
+    }
+  else
+    svn_skel__prepend_str("", prop_conflict, result_pool); /* No mine_props */
+
+  if (original_props)
+    {
+      SVN_ERR(svn_skel__unparse_proplist(&props, original_props, result_pool));
+      svn_skel__prepend(props, prop_conflict);
+    }
+  else
+    svn_skel__prepend_str("", prop_conflict, result_pool); /* No old_props */
+
+  conflict_names = svn_skel__make_empty_list(result_pool);
+  for (hi = apr_hash_first(scratch_pool, conflicted_prop_names);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      svn_skel__prepend_str(apr_pstrdup(result_pool,
+                                        svn__apr_hash_index_key(hi)),
+                            conflict_names,
+                            result_pool);
+    }
+  svn_skel__prepend(conflict_names, prop_conflict);
+
+  markers = svn_skel__make_empty_list(result_pool);
+
+  if (marker_abspath)
+    {
+      const char *marker_relpath;
+      SVN_ERR(svn_wc__db_to_relpath(&marker_relpath, db, wri_abspath,
+                                    marker_abspath,
+                                    result_pool, scratch_pool));
+
+      svn_skel__prepend_str(marker_relpath, markers, result_pool);
+    }
+  else
+    svn_skel__prepend(svn_skel__make_empty_list(result_pool), markers);
+
+  svn_skel__prepend(markers, prop_conflict);
+
+  svn_skel__prepend_str(SVN_WC__CONFLICT_KIND_PROP, prop_conflict, result_pool);
+
+  /* And add it to the conflict skel */
+  svn_skel__prepend(prop_conflict, conflict_skel->children->next);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__conflict_read_prop_conflict(const char **marker_abspath,
+                                    apr_hash_t **original_props,
+                                    apr_hash_t **mine_props,
+                                    apr_hash_t **their_props,
+                                    apr_hash_t **conflicted_prop_names,
+                                    svn_wc__db_t *db,
+                                    const char *wri_abspath,
+                                    svn_skel_t *conflict_skel,
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool)
+{
+  svn_skel_t *prop_conflict;
+  svn_skel_t *c;
+
+  SVN_ERR(conflict__get_conflict(&prop_conflict, conflict_skel,
+                                 SVN_WC__CONFLICT_KIND_PROP));
+
+  if (!prop_conflict)
+    return svn_error_create(SVN_ERR_WC_MISSING, NULL, _("Conflict not set"));
+
+  c = prop_conflict->children;
+
+  c = c->next; /* Skip "prop" */
+
+  /* Get marker file */
+  if (marker_abspath)
+    {
+      const char *marker_relpath;
+
+      if (c->children && c->children->is_atom)
+        {
+          marker_relpath = apr_pstrndup(result_pool, c->children->data,
+                                        c->children->len);
+
+          SVN_ERR(svn_wc__db_from_relpath(marker_abspath, db, wri_abspath,
+                                          marker_relpath,
+                                          result_pool, scratch_pool));
+        }
+      else
+        *marker_abspath = NULL;
+    }
+  c = c->next;
+
+  /* Get conflicted properties */
+  if (conflicted_prop_names)
+    {
+      svn_skel_t *name;
+      *conflicted_prop_names = apr_hash_make(result_pool);
+
+      for (name = c->children; name; name = name->next)
+        {
+          apr_hash_set(*conflicted_prop_names,
+                       apr_pstrndup(result_pool, name->data, name->len),
+                       APR_HASH_KEY_STRING,
+                       "");
+        }
+    }
+  c = c->next;
+
+  /* Get original properties */
+  if (original_props)
+    {
+      if (c->is_atom)
+        *original_props = apr_hash_make(result_pool);
+      else
+        SVN_ERR(svn_skel__parse_proplist(original_props, c, result_pool));
+    }
+  c = c->next;
+
+  /* Get mine properties */
+  if (mine_props)
+    {
+      if (c->is_atom)
+        *mine_props = apr_hash_make(result_pool);
+      else
+        SVN_ERR(svn_skel__parse_proplist(mine_props, c, result_pool));
+    }
+  c = c->next;
+
+  /* Get their properties */
+  if (their_props)
+    {
+      if (c->is_atom)
+        *their_props = apr_hash_make(result_pool);
+      else
+        SVN_ERR(svn_skel__parse_proplist(their_props, c, result_pool));
+    }
+  c = c->next;
+
+  return SVN_NO_ERROR;
+}
+
+/* --------------------------------------------------------------------
+ */
 svn_skel_t *
 svn_wc__prop_conflict_skel_new(apr_pool_t *result_pool)
 {

Modified: subversion/trunk/subversion/libsvn_wc/conflicts.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/conflicts.h?rev=1355012&r1=1355011&r2=1355012&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/conflicts.h (original)
+++ subversion/trunk/subversion/libsvn_wc/conflicts.h Thu Jun 28 13:49:35 2012
@@ -59,7 +59,7 @@ extern "C" {
    with the result of its operation in the working copy database.
 */
 svn_skel_t *
-svn_wc__conflict_skel_new(apr_pool_t *result_pool);
+svn_wc__conflict_skel_create(apr_pool_t *result_pool);
 
 /* Return a boolean in *COMPLETE indicating whether CONFLICT_SKEL contains
    everything needed for installing in the working copy database.

Modified: subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c?rev=1355012&r1=1355011&r2=1355012&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_wc/conflict-data-test.c Thu Jun 28 13:49:35 2012
@@ -20,7 +20,7 @@
  */
 
 /*
- * tree-conflict-data-test.c -- test the storage of tree conflict data
+ * conflict-data-test.c -- test the storage of tree conflict data
  */
 
 #include <stdio.h>
@@ -38,6 +38,7 @@
 #include "../../libsvn_wc/tree_conflicts.h"
 #include "../../libsvn_wc/wc.h"
 #include "../../libsvn_wc/wc_db.h"
+#include "../../libsvn_wc/conflicts.h"
 
 /* A quick way to create error messages.  */
 static svn_error_t *
@@ -291,6 +292,96 @@ test_read_write_tree_conflicts(const svn
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_serialize_prop_conflict(const svn_test_opts_t *opts,
+                             apr_pool_t *pool)
+{
+  svn_test__sandbox_t sbox;
+  svn_skel_t *conflict_skel;
+  svn_boolean_t complete;
+
+  SVN_ERR(svn_test__sandbox_create(&sbox, "test_serialize_prop_conflict", opts, pool));
+
+  conflict_skel = svn_wc__conflict_skel_create(pool);
+
+  SVN_TEST_ASSERT(conflict_skel != NULL);
+  SVN_TEST_ASSERT(svn_skel__list_length(conflict_skel) == 2);
+
+  SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel, pool));
+  SVN_TEST_ASSERT(!complete); /* Nothing set */
+
+  {
+    apr_hash_t *old = apr_hash_make(pool);
+    apr_hash_t *mine = apr_hash_make(pool);
+    apr_hash_t *theirs = apr_hash_make(pool);
+    apr_hash_t *conflicts = apr_hash_make(pool);
+    const char *marker_abspath;
+
+    apr_hash_set(old, "prop", APR_HASH_KEY_STRING,
+                 svn_string_create("Old", pool));
+
+    apr_hash_set(mine, "prop", APR_HASH_KEY_STRING,
+                 svn_string_create("Mine", pool));
+
+    apr_hash_set(theirs, "prop", APR_HASH_KEY_STRING,
+                 svn_string_create("Theirs", pool));
+
+    apr_hash_set(conflicts, "prop", APR_HASH_KEY_STRING, "");
+
+    SVN_ERR(svn_io_open_unique_file3(NULL, &marker_abspath, sbox.wc_abspath,
+                                     svn_io_file_del_on_pool_cleanup, pool,
+                                     pool));
+
+    SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_skel,
+                                                    sbox.wc_ctx->db,
+                                                    sbox.wc_abspath,
+                                                    marker_abspath,
+                                                    old, mine, theirs,
+                                                    conflicts,
+                                                    pool, pool));
+  }
+
+  SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel, pool));
+  SVN_TEST_ASSERT(!complete); /* Misses operation */
+
+  /* TODO: Set operation and verify complete */
+
+  {
+    apr_hash_t *old;
+    apr_hash_t *mine;
+    apr_hash_t *theirs;
+    apr_hash_t *conflicts;
+    const char *marker_abspath;
+    svn_string_t *v;
+
+    SVN_ERR(svn_wc__conflict_read_prop_conflict(&marker_abspath,
+                                                &old,
+                                                &mine,
+                                                &theirs,
+                                                &conflicts,
+                                                sbox.wc_ctx->db,
+                                                sbox.wc_abspath,
+                                                conflict_skel,
+                                                pool, pool));
+
+    SVN_TEST_ASSERT(svn_dirent_is_ancestor(sbox.wc_abspath, marker_abspath));
+
+    v = apr_hash_get(old, "prop", APR_HASH_KEY_STRING);
+    SVN_TEST_STRING_ASSERT(v->data, "Old");
+
+    v = apr_hash_get(mine, "prop", APR_HASH_KEY_STRING);
+    SVN_TEST_STRING_ASSERT(v->data, "Mine");
+
+    v = apr_hash_get(theirs, "prop", APR_HASH_KEY_STRING);
+    SVN_TEST_STRING_ASSERT(v->data, "Theirs");
+
+    SVN_TEST_ASSERT(apr_hash_count(conflicts) == 1);
+  }
+
+  return SVN_NO_ERROR;
+}
+
+
 /* The test table.  */
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -302,6 +393,8 @@ struct svn_test_descriptor_t test_funcs[
                    "serialize tree conflict"),
     SVN_TEST_OPTS_PASS(test_read_write_tree_conflicts,
                        "read and write tree conflicts"),
+    SVN_TEST_OPTS_PASS(test_serialize_prop_conflict,
+                       "read and write a property conflict"),
     SVN_TEST_NULL
   };
 



Re: svn commit: r1355012 - in /subversion/trunk/subversion: libsvn_wc/conflicts.c libsvn_wc/conflicts.h tests/libsvn_wc/conflict-data-test.c

Posted by Greg Stein <gs...@gmail.com>.
On Thu, Jun 28, 2012 at 1:26 PM, Bert Huijben <be...@qqmail.nl> wrote:
>...
>> If there is no MARKER_ABSPATH, then you end up with (()) rather than just
>> ().
>
> This is documented as a special allowed value, but my next patch will remove
> it anyway (as it keeps the property unneeded hard to fill this value
> directly). This will add an empty list and add the item right before
> installing in the db.

But the storage doc says () for "no marker files". So why should there
be an additional empty list in there?

Cheers,
-g

RE: svn commit: r1355012 - in /subversion/trunk/subversion: libsvn_wc/conflicts.c libsvn_wc/conflicts.h tests/libsvn_wc/conflict-data-test.c

Posted by Bert Huijben <be...@qqmail.nl>.

> -----Original Message-----
> From: Greg Stein [mailto:gstein@gmail.com]
> Sent: donderdag 28 juni 2012 19:16
> To: dev@subversion.apache.org
> Subject: Re: svn commit: r1355012 - in /subversion/trunk/subversion:
> libsvn_wc/conflicts.c libsvn_wc/conflicts.h tests/libsvn_wc/conflict-data-
> test.c
> 
> On Thu, Jun 28, 2012 at 9:49 AM,  <rh...@apache.org> wrote:
> >...
> > +++ subversion/trunk/subversion/libsvn_wc/conflicts.c Thu Jun 28
13:49:35
> 2012
> >...
> > +static svn_error_t *
> > +conflict__get_conflict(svn_skel_t **conflict,
> > +                       svn_skel_t *conflict_skel,
> > +                       const char *conflict_type)
> > +{
> > +  svn_skel_t *c;
> > +  apr_size_t len;
> > +  SVN_ERR_ASSERT(conflict_skel
> > +                 && conflict_skel->children
> > +                 && conflict_skel->children->next
> > +                 && !conflict_skel->children->next->is_atom);
> > +
> > +  len = strlen(conflict_type);
> > +
> > +  for(c = conflict_skel->children->next->children;
> > +      c;
> > +      c = c->next)
> > +    {
> > +      if (c->children->is_atom
> > +          && c->children->len == len
> > +          && memcmp(c->children->data, conflict_type, len) == 0)
> 
> Please use svn_skel__matches_atom() for clarity.

Thanks, didn't know about that function.

> 
> >...
> > +  markers = svn_skel__make_empty_list(result_pool);
> > +
> > +  if (marker_abspath)
> > +    {
> > +      const char *marker_relpath;
> > +      SVN_ERR(svn_wc__db_to_relpath(&marker_relpath, db,
> wri_abspath,
> > +                                    marker_abspath,
> > +                                    result_pool, scratch_pool));
> > +
> > +      svn_skel__prepend_str(marker_relpath, markers, result_pool);
> > +    }
> > +  else
> > +    svn_skel__prepend(svn_skel__make_empty_list(result_pool),
> markers);
> > +
> > +  svn_skel__prepend(markers, prop_conflict);
> 
> If there is no MARKER_ABSPATH, then you end up with (()) rather than just
> ().

This is documented as a special allowed value, but my next patch will remove
it anyway (as it keeps the property unneeded hard to fill this value
directly). This will add an empty list and add the item right before
installing in the db.

Thanks,
	Bert
> 
> >...
> 
> Cheers,
> -g


Re: svn commit: r1355012 - in /subversion/trunk/subversion: libsvn_wc/conflicts.c libsvn_wc/conflicts.h tests/libsvn_wc/conflict-data-test.c

Posted by Greg Stein <gs...@gmail.com>.
On Thu, Jun 28, 2012 at 9:49 AM,  <rh...@apache.org> wrote:
>...
> +++ subversion/trunk/subversion/libsvn_wc/conflicts.c Thu Jun 28 13:49:35 2012
>...
> +static svn_error_t *
> +conflict__get_conflict(svn_skel_t **conflict,
> +                       svn_skel_t *conflict_skel,
> +                       const char *conflict_type)
> +{
> +  svn_skel_t *c;
> +  apr_size_t len;
> +  SVN_ERR_ASSERT(conflict_skel
> +                 && conflict_skel->children
> +                 && conflict_skel->children->next
> +                 && !conflict_skel->children->next->is_atom);
> +
> +  len = strlen(conflict_type);
> +
> +  for(c = conflict_skel->children->next->children;
> +      c;
> +      c = c->next)
> +    {
> +      if (c->children->is_atom
> +          && c->children->len == len
> +          && memcmp(c->children->data, conflict_type, len) == 0)

Please use svn_skel__matches_atom() for clarity.

>...
> +  markers = svn_skel__make_empty_list(result_pool);
> +
> +  if (marker_abspath)
> +    {
> +      const char *marker_relpath;
> +      SVN_ERR(svn_wc__db_to_relpath(&marker_relpath, db, wri_abspath,
> +                                    marker_abspath,
> +                                    result_pool, scratch_pool));
> +
> +      svn_skel__prepend_str(marker_relpath, markers, result_pool);
> +    }
> +  else
> +    svn_skel__prepend(svn_skel__make_empty_list(result_pool), markers);
> +
> +  svn_skel__prepend(markers, prop_conflict);

If there is no MARKER_ABSPATH, then you end up with (()) rather than just ().

>...

Cheers,
-g