Author: rhuijben
Date: Thu Dec 13 17:17:40 2012
New Revision: 1421391

URL: http://svn.apache.org/viewvc?rev=1421391&view=rev
Log:
Switch the property merge code implementation to use explicit output arguments
instead of updating a passed apr_hash_t and state.

* subversion/libsvn_wc/props.c
  (apply_single_prop_add,
   apply_single_prop_delete,
   apply_single_mergeinfo_prop_change,
   apply_single_generic_prop_change,
   apply_single_prop_change): Move updating the property hash and state from
      here to ...
  (svn_wc__merge_props): ... here.

Modified:
    subversion/trunk/subversion/libsvn_wc/props.c

Modified: subversion/trunk/subversion/libsvn_wc/props.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/props.c?rev=1421391&r1=1421390&r2=1421391&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/props.c (original)
+++ subversion/trunk/subversion/libsvn_wc/props.c Thu Dec 13 17:17:40 2012
@@ -738,30 +738,26 @@ set_prop_merge_state(svn_wc_notify_state
   *state = new_value;
 }
 
-/* Add the property with name PROPNAME to the set of ACTUAL_PROPS,
- * setting *STATE or *CONFLICT_REMAINS according to the merge outcome.
- *
- * *STATE is an input and output parameter, its value is to be
- * set using set_merge_prop_state().
+/* Apply the addition of a property with name PROPNAME and value NEW_VAL to
+ * the existing property with value WORKING_VAL, that originally had value
+ * PRISTINE_VAL.
  *
- * BASE_VAL contains the working copy base property value
- *
- * NEW_VAL contains the value to be set.
+ * Sets *RESULT_VAL to the resulting value.
+ * Sets *CONFLICT_REMAINS to TRUE if the change caused a conflict.
+ * Sets *DID_MERGE to true if the result is caused by a merge
  */
 static svn_error_t *
-apply_single_prop_add(svn_wc_notify_state_t *state,
+apply_single_prop_add(const svn_string_t **result_val,
                       svn_boolean_t *conflict_remains,
-                      apr_hash_t *actual_props,
+                      svn_boolean_t *did_merge,
                       const char *propname,
-                      const svn_string_t *base_val,
+                      const svn_string_t *pristine_val,
                       const svn_string_t *new_val,
+                      const svn_string_t *working_val,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
 
 {
-  svn_string_t *working_val
-    = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING);
-
   *conflict_remains = FALSE;
 
   if (working_val)
@@ -770,7 +766,7 @@ apply_single_prop_add(svn_wc_notify_stat
 
       if (svn_string_compare(working_val, new_val))
         /* The value we want is already there, so it's a merge. */
-        set_prop_merge_state(state, svn_wc_notify_state_merged);
+        *did_merge = TRUE;
 
       else
         {
@@ -800,9 +796,8 @@ apply_single_prop_add(svn_wc_notify_stat
               else
                 {
                   merged_prop = TRUE;
-                  apr_hash_set(actual_props, propname,
-                               APR_HASH_KEY_STRING, merged_val);
-                  set_prop_merge_state(state, svn_wc_notify_state_merged);
+                  *result_val = merged_val;
+                  *did_merge = TRUE;
                 }
             }
 
@@ -810,40 +805,34 @@ apply_single_prop_add(svn_wc_notify_stat
             *conflict_remains = TRUE;
         }
     }
-  else if (base_val)
+  else if (pristine_val)
     *conflict_remains = TRUE;
   else  /* property doesn't yet exist in actual_props...  */
     /* so just set it */
-    apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, new_val);
+    *result_val = new_val;
 
   return SVN_NO_ERROR;
 }
 
 
-/* Delete the property with name PROPNAME from the set of ACTUAL_PROPS,
- * setting *STATE or *CONFLICT_REMAINS according to the merge outcome.
- *
- * *STATE is an input and output parameter, its value is to be
- * set using set_merge_prop_state().
+/* Apply the deletion of a property with name PROPNAME to the existing
+ * property with value WORKING_VAL, that originally had value PRISTINE_VAL.
  *
- * BASE_VAL contains the working copy base property value
- *
- * OLD_VAL contains the value the of the property the server
- * thinks it's deleting.
+ * Sets *RESULT_VAL to the resulting value.
+ * Sets *CONFLICT_REMAINS to TRUE if the change caused a conflict.
+ * Sets *DID_MERGE to true if the result is caused by a merge
  */
 static svn_error_t *
-apply_single_prop_delete(svn_wc_notify_state_t *state,
+apply_single_prop_delete(const svn_string_t **result_val,
                          svn_boolean_t *conflict_remains,
-                         apr_hash_t *actual_props,
+                         svn_boolean_t *did_merge,
                          const char *propname,
                          const svn_string_t *base_val,
                          const svn_string_t *old_val,
+                         const svn_string_t *working_val,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
-  svn_string_t *working_val
-    = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING);
-
   *conflict_remains = FALSE;
 
   if (! base_val)
@@ -856,11 +845,11 @@ apply_single_prop_delete(svn_wc_notify_s
         }
       else
         {
-          apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, NULL);
+          *result_val = NULL;
           if (old_val)
             /* This is a merge, merging a delete into non-existent
                property or a local addition of same prop value. */
-            set_prop_merge_state(state, svn_wc_notify_state_merged);
+            *did_merge = TRUE;
         }
     }
 
@@ -870,14 +859,14 @@ apply_single_prop_delete(svn_wc_notify_s
          {
            if (svn_string_compare(working_val, old_val))
              /* they have the same values, so it's an update */
-             apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, NULL);
+             *result_val = NULL;
            else
              *conflict_remains = TRUE;
          }
        else
          /* The property is locally deleted from the same value, so it's
             a merge */
-         set_prop_merge_state(state, svn_wc_notify_state_merged);
+         *did_merge = TRUE;
     }
 
   else
@@ -895,19 +884,17 @@ apply_single_prop_delete(svn_wc_notify_s
    were not followed for this property, but with no attempt to rationalize
    the remainder. */
 static svn_error_t *
-apply_single_mergeinfo_prop_change(svn_wc_notify_state_t *state,
+apply_single_mergeinfo_prop_change(const svn_string_t **result_val,
                                    svn_boolean_t *conflict_remains,
-                                   apr_hash_t *actual_props,
+                                   svn_boolean_t *did_merge,
                                    const char *propname,
                                    const svn_string_t *base_val,
                                    const svn_string_t *old_val,
                                    const svn_string_t *new_val,
+                                   const svn_string_t *working_val,
                                    apr_pool_t *result_pool,
                                    apr_pool_t *scratch_pool)
 {
-  svn_string_t *working_val
-    = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING);
-
   if ((working_val && ! base_val)
       || (! working_val && base_val)
       || (working_val && base_val
@@ -918,7 +905,7 @@ apply_single_mergeinfo_prop_change(svn_w
         {
           if (svn_string_compare(working_val, new_val))
             /* The new value equals the changed value: a no-op merge */
-            set_prop_merge_state(state, svn_wc_notify_state_merged);
+            *did_merge = TRUE;
           else
             {
               /* We have base, WC, and new values.  Discover
@@ -930,12 +917,10 @@ apply_single_mergeinfo_prop_change(svn_w
                                                      new_val,
                                                      result_pool,
                                                      scratch_pool));
-              apr_hash_set(actual_props, propname,
-                           APR_HASH_KEY_STRING, new_val);
-              set_prop_merge_state(state, svn_wc_notify_state_merged);
+              *result_val = new_val;
+              *did_merge = TRUE;
             }
         }
-
       else
         {
           /* There is a base_val but no working_val */
@@ -957,15 +942,13 @@ apply_single_mergeinfo_prop_change(svn_w
                                    old_val, new_val, scratch_pool));
       SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string,
                                       added_mergeinfo, result_pool));
-      apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING,
-                   mergeinfo_string);
+      *result_val = mergeinfo_string;
     }
 
   else /* means working && base && svn_string_compare(working, base) */
     {
       if (svn_string_compare(old_val, base_val))
-        apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, new_val);
-
+        *result_val = new_val;
       else
         {
           /* We have base, WC, and new values.  Discover
@@ -976,9 +959,8 @@ apply_single_mergeinfo_prop_change(svn_w
                                                  working_val,
                                                  new_val, result_pool,
                                                  scratch_pool));
-          apr_hash_set(actual_props, propname,
-                       APR_HASH_KEY_STRING, new_val);
-          set_prop_merge_state(state, svn_wc_notify_state_merged);
+          *result_val = new_val;
+          *did_merge = TRUE;
         }
     }
 
@@ -992,19 +974,17 @@ apply_single_mergeinfo_prop_change(svn_w
    The definition of the arguments and behaviour is the same as
    apply_single_prop_change(). */
 static svn_error_t *
-apply_single_generic_prop_change(svn_wc_notify_state_t *state,
+apply_single_generic_prop_change(const svn_string_t **result_val,
                                  svn_boolean_t *conflict_remains,
-                                 apr_hash_t *actual_props,
+                                 svn_boolean_t *did_merge,
                                  const char *propname,
                                  const svn_string_t *base_val,
                                  const svn_string_t *old_val,
                                  const svn_string_t *new_val,
+                                 const svn_string_t *working_val,
                                  apr_pool_t *result_pool,
                                  apr_pool_t *scratch_pool)
 {
-  svn_string_t *working_val
-    = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING);
-
   SVN_ERR_ASSERT(old_val != NULL);
 
   /* If working_val is the same as new_val already then there is
@@ -1014,14 +994,14 @@ apply_single_generic_prop_change(svn_wc_
     {
       /* All values identical is a trivial, non-notifiable merge */
       if (! old_val || ! svn_string_compare(old_val, new_val))
-        set_prop_merge_state(state, svn_wc_notify_state_merged);
+        *did_merge = TRUE;
     }
   /* If working_val is the same as old_val... */
   else if (working_val && old_val
       && svn_string_compare(working_val, old_val))
     {
       /* A trivial update: change it to new_val. */
-      apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING, new_val);
+      *result_val = new_val;
     }
   else
     {
@@ -1046,13 +1026,14 @@ apply_single_generic_prop_change(svn_wc_
  * NEW_VAL contains the value to be set. (Not null.)
  */
 static svn_error_t *
-apply_single_prop_change(svn_wc_notify_state_t *state,
+apply_single_prop_change(const svn_string_t **result_val,
                          svn_boolean_t *conflict_remains,
-                         apr_hash_t *actual_props,
+                         svn_boolean_t *did_merge,
                          const char *propname,
                          const svn_string_t *base_val,
                          const svn_string_t *old_val,
                          const svn_string_t *new_val,
+                         const svn_string_t *working_val,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
@@ -1075,13 +1056,14 @@ apply_single_prop_change(svn_wc_notify_s
          gracefully' might thwart us.  If bogus mergeinfo is present we
          can't merge intelligently, so let the standard method deal with
          it instead. */
-      svn_error_t *err = apply_single_mergeinfo_prop_change(state,
+      svn_error_t *err = apply_single_mergeinfo_prop_change(result_val,
                                                             conflict_remains,
-                                                            actual_props,
+                                                            did_merge,
                                                             propname,
                                                             base_val,
                                                             old_val,
                                                             new_val,
+                                                            working_val,
                                                             result_pool,
                                                             scratch_pool);
        if (err)
@@ -1102,10 +1084,10 @@ apply_single_prop_change(svn_wc_notify_s
       /* The standard method: perform a simple update automatically, but
          pass any other kind of merge to maybe_generate_propconflict(). */
 
-      SVN_ERR(apply_single_generic_prop_change(state, conflict_remains,
-                                               actual_props,
+      SVN_ERR(apply_single_generic_prop_change(result_val, conflict_remains,
+                                               did_merge,
                                                propname, base_val, old_val,
-                                               new_val,
+                                               new_val, working_val,
                                                result_pool, scratch_pool));
     }
 
@@ -1163,6 +1145,9 @@ svn_wc__merge_props(svn_skel_t **conflic
       const svn_string_t *base_val; /* Pristine in WC */
       const svn_string_t *from_val; /* Merge left */
       const svn_string_t *to_val; /* Merge right */
+      const svn_string_t *working_val; /* Mine */
+      const svn_string_t *result_val;
+      svn_boolean_t did_merge = FALSE;
 
       svn_pool_clear(iterpool);
 
@@ -1174,36 +1159,45 @@ svn_wc__merge_props(svn_skel_t **conflic
       from_val = apr_hash_get(server_baseprops, propname, APR_HASH_KEY_STRING);
 
       base_val = apr_hash_get(pristine_props, propname, APR_HASH_KEY_STRING);
+      working_val = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING);
 
       if (new_pristine_props)
         apr_hash_set(*new_pristine_props, propname, APR_HASH_KEY_STRING,
                      to_val);
 
       apr_hash_set(their_props, propname, APR_HASH_KEY_STRING, to_val);
+      
 
       /* We already know that state is at least `changed', so mark
          that, but remember that we may later upgrade to `merged' or
          even `conflicted'. */
       set_prop_merge_state(state, svn_wc_notify_state_changed);
 
+      result_val = working_val;
+
       if (! from_val)  /* adding a new property */
-        SVN_ERR(apply_single_prop_add(state, &conflict_remains,
-                                      *new_actual_props,
-                                      propname, base_val, to_val,
+        SVN_ERR(apply_single_prop_add(&result_val, &conflict_remains,
+                                      &did_merge, propname,
+                                      base_val, to_val, working_val,
                                       result_pool, iterpool));
 
       else if (! to_val) /* delete an existing property */
-        SVN_ERR(apply_single_prop_delete(state, &conflict_remains,
-                                         *new_actual_props,
-                                         propname, base_val, from_val,
+        SVN_ERR(apply_single_prop_delete(&result_val, &conflict_remains,
+                                         &did_merge, propname,
+                                         base_val, from_val, working_val,
                                          result_pool, iterpool));
 
       else  /* changing an existing property */
-        SVN_ERR(apply_single_prop_change(state, &conflict_remains,
-                                         *new_actual_props,
-                                         propname, base_val, from_val, to_val,
+        SVN_ERR(apply_single_prop_change(&result_val, &conflict_remains,
+                                         &did_merge, propname,
+                                         base_val, from_val, to_val, 
working_val,
                                          result_pool, iterpool));
 
+      if (result_val != working_val)
+        apr_hash_set(*new_actual_props, propname, APR_HASH_KEY_STRING,
+                     result_val);
+      if (did_merge)
+        set_prop_merge_state(state, svn_wc_notify_state_merged);
 
       /* merging logic complete, now we need to possibly log conflict
          data to tmpfiles.  */


Reply via email to