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/05/10 21:13:12 UTC

svn commit: r1336833 - in /subversion/trunk/subversion: include/svn_wc.h libsvn_client/merge.c libsvn_wc/deprecated.c libsvn_wc/merge.c

Author: rhuijben
Date: Thu May 10 19:13:11 2012
New Revision: 1336833

URL: http://svn.apache.org/viewvc?rev=1336833&view=rev
Log:
Make the text and property merge handling of 'svn merge' of a single file an
atomic operation by moving the handling into a single libsvn_wc call that
installs or doesn't install the working queue items.

* subversion/include/svn_wc.h
  (svn_wc_merge5): New function.
  (svn_wc_merge4): Deprecate function.

* subversion/libsvn_client/merge.c
  (merge_file_changed): Update caller.

* subversion/libsvn_wc/deprecated.c
  (svn_wc_merge4): New function. Wraps svn_wc_merge5().

* subversion/libsvn_wc/merge.c
  (svn_wc_merge4): Rename to ...
  (svn_wc_merge5): ... this and add support for merging properties in the same
    operation. At the same time avoid a few more unneeded db operations.

Modified:
    subversion/trunk/subversion/include/svn_wc.h
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_wc/deprecated.c
    subversion/trunk/subversion/libsvn_wc/merge.c

Modified: subversion/trunk/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1336833&r1=1336832&r2=1336833&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Thu May 10 19:13:11 2012
@@ -6575,7 +6575,7 @@ typedef enum svn_wc_merge_outcome_t
  * receive the changes, then translated back again.
  *
  * If @a target_abspath is absent, or present but not under version
- * control, then set @a *merge_outcome to #svn_wc_merge_no_merge and
+ * control, then set @a *merge_content_outcome to #svn_wc_merge_no_merge and
  * return success without merging anything.  (The reasoning is that if
  * the file is not versioned, then it is probably unrelated to the
  * changes being considered, so they should not be merged into it.
@@ -6593,8 +6593,16 @@ typedef enum svn_wc_merge_outcome_t
  * svn_diff_file_options_parse()).  @a merge_options must contain
  * <tt>const char *</tt> elements.
  *
- * The outcome of the merge is returned in @a *merge_outcome. If there
- * is a conflict and @a dry_run is @c FALSE, then attempt to call @a
+ * If @a merge_props_state is non-NULL @a propchanges is merged before
+ * merging the text. (If @a merge_props_outcome is NULL, no property changes
+*  are merged and @a prop_changes is only used to determine the merge result)
+ * The result of the property merge is stored in @a *merge_props_state. If
+ * there is a conflict and @a dry_run is @c FALSE, then attempt to call @a
+ * conflict_func with @a conflict_baton (if non-NULL).  If the conflict
+ * callback cannot resolve the conflict, then a property conflict is installed.
+ *
+ * The outcome of the text merge is returned in @a *merge_text_outcome. If
+ * there is a conflict and @a dry_run is @c FALSE, then attempt to call @a
  * conflict_func with @a conflict_baton (if non-NULL).  If the
  * conflict callback cannot resolve the conflict, then:
  *
@@ -6629,9 +6637,39 @@ typedef enum svn_wc_merge_outcome_t
  *
  * Use @a scratch_pool for any temporary allocation.
  *
+ * @since New in 1.8.
+ */ /* ### BH: Two kinds of outcome is not how it should be */
+svn_error_t *
+svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
+              enum svn_wc_notify_state_t *merge_props_state,
+              svn_wc_context_t *wc_ctx,
+              const char *left_abspath,
+              const char *right_abspath,
+              const char *target_abspath,
+              const char *left_label,
+              const char *right_label,
+              const char *target_label,
+              const svn_wc_conflict_version_t *left_version,
+              const svn_wc_conflict_version_t *right_version,
+              svn_boolean_t dry_run,
+              const char *diff3_cmd,
+              const apr_array_header_t *merge_options,
+              apr_hash_t *original_props,
+              const apr_array_header_t *prop_diff,
+              svn_wc_conflict_resolver_func2_t conflict_func,
+              void *conflict_baton,
+              svn_cancel_func_t cancel_func,
+              void *cancel_baton,
+              apr_pool_t *scratch_pool);
+
+/** Similar to svn_wc_merge4() but doesn't allow property changes. Instead of
+ * handling this in a single operation, a separate call to svn_wc_merge_props3()
+ * before calling svn_wc_merge4() is needed
+ *
  * @since New in 1.7.
+ * @deprecated Provided for backwards compatibility with the 1.7 API.
  */
-svn_error_t *
+SVN_DEPRECATED svn_error_t *
 svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
               svn_wc_context_t *wc_ctx,
               const char *left_abspath,
@@ -6652,6 +6690,7 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
               void *cancel_baton,
               apr_pool_t *scratch_pool);
 
+
 /** Similar to svn_wc_merge4() but takes relative paths and an access
  * baton. It doesn't support a cancel function or tracking origin version
  * information.

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1336833&r1=1336832&r2=1336833&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Thu May 10 19:13:11 2012
@@ -1535,7 +1535,7 @@ merge_file_changed(svn_wc_notify_state_t
 
   /* Other easy outs:  if the merge target isn't under version
      control, or is just missing from disk, fogettaboutit.  There's no
-     way svn_wc_merge4() can do the merge. */
+     way svn_wc_merge5() can do the merge. */
   if (wc_kind != svn_node_file || is_deleted)
     {
       const char *moved_to_abspath;
@@ -1623,7 +1623,7 @@ merge_file_changed(svn_wc_notify_state_t
   */
 
   /* This callback is essentially no more than a wrapper around
-     svn_wc_merge4().  Thank goodness that all the
+     svn_wc_merge5().  Thank goodness that all the
      diff-editor-mechanisms are doing the hard work of getting the
      fulltexts! */
 
@@ -1669,7 +1669,7 @@ merge_file_changed(svn_wc_notify_state_t
   if (older_abspath)
     {
       svn_boolean_t has_local_mods;
-      enum svn_wc_merge_outcome_t merge_outcome;
+      enum svn_wc_merge_outcome_t content_outcome;
 
       /* xgettext: the '.working', '.merge-left.r%ld' and
          '.merge-right.r%ld' strings are used to tag onto a file
@@ -1691,26 +1691,15 @@ merge_file_changed(svn_wc_notify_state_t
       conflict_baton.conflicted_paths = &merge_b->conflicted_paths;
       conflict_baton.pool = merge_b->pool;
 
-      /* Do property merge before text merge so that keyword expansion takes
-         into account the new property values. */
-      if (prop_changes)
-        {
-          SVN_ERR(svn_wc_merge_props3(prop_state, ctx->wc_ctx, local_abspath,
-                                      left, right,
-                                      original_props, prop_changes,
-                                      merge_b->dry_run,
-                                      ctx->conflict_func2,
-                                      ctx->conflict_baton2,
-                                      ctx->cancel_func, ctx->cancel_baton,
-                                      scratch_pool));
-        }
-
-      SVN_ERR(svn_wc_merge4(&merge_outcome, ctx->wc_ctx,
+      /* Do property merge and text merge in one step so that keyword expansion
+         takes into account the new property values. */
+      SVN_ERR(svn_wc_merge5(&content_outcome, prop_state, ctx->wc_ctx,
                             older_abspath, yours_abspath, local_abspath,
                             left_label, right_label, target_label,
                             left, right,
                             merge_b->dry_run, merge_b->diff3_cmd,
-                            merge_b->merge_options, prop_changes,
+                            merge_b->merge_options,
+                            original_props, prop_changes,
                             conflict_resolver, &conflict_baton,
                             ctx->cancel_func,
                             ctx->cancel_baton,
@@ -1718,14 +1707,14 @@ merge_file_changed(svn_wc_notify_state_t
 
       if (content_state)
         {
-          if (merge_outcome == svn_wc_merge_conflict)
+          if (content_outcome == svn_wc_merge_conflict)
             *content_state = svn_wc_notify_state_conflicted;
           else if (has_local_mods
-                   && merge_outcome != svn_wc_merge_unchanged)
+                   && content_outcome != svn_wc_merge_unchanged)
             *content_state = svn_wc_notify_state_merged;
-          else if (merge_outcome == svn_wc_merge_merged)
+          else if (content_outcome == svn_wc_merge_merged)
             *content_state = svn_wc_notify_state_changed;
-          else if (merge_outcome == svn_wc_merge_no_merge)
+          else if (content_outcome == svn_wc_merge_no_merge)
             *content_state = svn_wc_notify_state_missing;
           else /* merge_outcome == svn_wc_merge_unchanged */
             *content_state = svn_wc_notify_state_unchanged;

Modified: subversion/trunk/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/deprecated.c?rev=1336833&r1=1336832&r2=1336833&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_wc/deprecated.c Thu May 10 19:13:11 2012
@@ -4185,6 +4185,49 @@ svn_wc_copy(const char *src_path,
 /*** From merge.c ***/
 
 svn_error_t *
+svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
+              svn_wc_context_t *wc_ctx,
+              const char *left_abspath,
+              const char *right_abspath,
+              const char *target_abspath,
+              const char *left_label,
+              const char *right_label,
+              const char *target_label,
+              const svn_wc_conflict_version_t *left_version,
+              const svn_wc_conflict_version_t *right_version,
+              svn_boolean_t dry_run,
+              const char *diff3_cmd,
+              const apr_array_header_t *merge_options,
+              const apr_array_header_t *prop_diff,
+              svn_wc_conflict_resolver_func2_t conflict_func,
+              void *conflict_baton,
+              svn_cancel_func_t cancel_func,
+              void *cancel_baton,
+              apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(
+            svn_wc_merge5(merge_outcome,
+                          NULL /* merge_props_outcome */,
+                          wc_ctx,
+                          left_abspath,
+                          right_abspath,
+                          target_abspath,
+                          left_label,
+                          right_label,
+                          target_label,
+                          left_version,
+                          right_version,
+                          dry_run,
+                          diff3_cmd,
+                          merge_options,
+                          NULL /* original_props */,
+                          prop_diff,
+                          conflict_func, conflict_baton,
+                          cancel_func, cancel_baton,
+                          scratch_pool));
+}
+
+svn_error_t *
 svn_wc_merge3(enum svn_wc_merge_outcome_t *merge_outcome,
               const char *left,
               const char *right,

Modified: subversion/trunk/subversion/libsvn_wc/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/merge.c?rev=1336833&r1=1336832&r2=1336833&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/merge.c (original)
+++ subversion/trunk/subversion/libsvn_wc/merge.c Thu May 10 19:13:11 2012
@@ -1476,7 +1476,8 @@ svn_wc__internal_merge(svn_skel_t **work
 
 
 svn_error_t *
-svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
+svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
+              enum svn_wc_notify_state_t *merge_props_outcome,
               svn_wc_context_t *wc_ctx,
               const char *left_abspath,
               const char *right_abspath,
@@ -1489,6 +1490,7 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
               svn_boolean_t dry_run,
               const char *diff3_cmd,
               const apr_array_header_t *merge_options,
+              apr_hash_t *original_props,
               const apr_array_header_t *prop_diff,
               svn_wc_conflict_resolver_func2_t conflict_func,
               void *conflict_baton,
@@ -1497,8 +1499,11 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
               apr_pool_t *scratch_pool)
 {
   const char *dir_abspath = svn_dirent_dirname(target_abspath, scratch_pool);
+  svn_skel_t *prop_items = NULL;
   svn_skel_t *work_items;
-  apr_hash_t *actual_props;
+  apr_hash_t *pristine_props = NULL;
+  apr_hash_t *actual_props = NULL;
+  apr_hash_t *new_actual_props = NULL;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(left_abspath));
   SVN_ERR_ASSERT(svn_dirent_is_absolute(right_abspath));
@@ -1508,37 +1513,86 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
   if (!dry_run)
     SVN_ERR(svn_wc__write_check(wc_ctx->db, dir_abspath, scratch_pool));
 
-  /* Sanity check:  the merge target must be under revision control,
-   * unless the merge target is a copyfrom text, which lives in a
-   * temporary file and does not exist in ACTUAL yet. */
+  /* Sanity check:  the merge target must be a file under revision control */
   {
+    svn_wc__db_status_t status;
     svn_kind_t kind;
-    svn_boolean_t hidden;
-    SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, target_abspath, TRUE,
-                                 scratch_pool));
+    svn_boolean_t had_props;
+    svn_boolean_t props_mod;
 
-    if (kind == svn_kind_unknown)
+    SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+                                 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                                 NULL, &had_props, &props_mod, NULL, NULL,
+                                 NULL,
+                                 wc_ctx->db, target_abspath,
+                                 scratch_pool, scratch_pool));
+
+    if (kind != svn_kind_file || (status != svn_wc__db_status_normal
+                                  && status != svn_wc__db_status_added))
       {
-        *merge_outcome = svn_wc_merge_no_merge;
+        *merge_content_outcome = svn_wc_merge_no_merge;
+        if (merge_props_outcome)
+          *merge_props_outcome = svn_wc_merge_no_merge;
         return SVN_NO_ERROR;
       }
 
-    SVN_ERR(svn_wc__db_node_hidden(&hidden, wc_ctx->db, target_abspath,
-                                   scratch_pool));
+    if (merge_props_outcome && had_props)
+      {
+        SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props,
+                                               wc_ctx->db, target_abspath,
+                                               scratch_pool, scratch_pool));
+      }
+    else if (merge_props_outcome)
+      pristine_props = apr_hash_make(scratch_pool);
 
-    if (hidden)
+    if (props_mod)
       {
-        *merge_outcome = svn_wc_merge_no_merge;
-        return SVN_NO_ERROR;
+        SVN_ERR(svn_wc__db_read_props(&actual_props,
+                                      wc_ctx->db, target_abspath,
+                                      scratch_pool, scratch_pool));
       }
+    else if (pristine_props)
+      actual_props = apr_hash_copy(scratch_pool, pristine_props);
+    else
+      actual_props = apr_hash_make(scratch_pool);
   }
 
-  SVN_ERR(svn_wc__db_read_props(&actual_props, wc_ctx->db, target_abspath,
-                                scratch_pool, scratch_pool));
+  if (merge_props_outcome)
+    {
+      int i;
+      apr_hash_t *new_pristine_props;
+      /* The PROPCHANGES may not have non-"normal" properties in it. If entry
+         or wc props were allowed, then the following code would install them
+         into the BASE and/or WORKING properties(!).  */
+      for (i = prop_diff->nelts; i--; )
+        {
+          const svn_prop_t *change = &APR_ARRAY_IDX(prop_diff, i, svn_prop_t);
+
+          if (!svn_wc_is_normal_prop(change->name))
+            return svn_error_createf(SVN_ERR_BAD_PROP_KIND, NULL,
+                                     _("The property '%s' may not be merged "
+                                       "into '%s'."),
+                                     change->name,
+                                     svn_dirent_local_style(target_abspath,
+                                                            scratch_pool));
+        }
+
+      SVN_ERR(svn_wc__merge_props(&prop_items, merge_props_outcome,
+                                  &new_pristine_props, &new_actual_props,
+                                  wc_ctx->db, target_abspath, svn_kind_file,
+                                  left_version, right_version,
+                                  original_props, pristine_props, actual_props,
+                                  prop_diff, FALSE /* base_merge */,
+                                  dry_run,
+                                  conflict_func, conflict_baton,
+                                  cancel_func, cancel_baton,
+                                  scratch_pool, scratch_pool));
+    }
 
   /* Queue all the work.  */
   SVN_ERR(svn_wc__internal_merge(&work_items,
-                                 merge_outcome,
+                                 merge_content_outcome,
                                  wc_ctx->db,
                                  left_abspath, left_version,
                                  right_abspath, right_version,
@@ -1554,16 +1608,24 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
                                  cancel_func, cancel_baton,
                                  scratch_pool, scratch_pool));
 
+  work_items = svn_wc__wq_merge(prop_items, work_items, scratch_pool);
+
   /* If this isn't a dry run, then run the work!  */
   if (!dry_run)
     {
-      SVN_ERR(svn_wc__db_wq_add(wc_ctx->db, target_abspath, work_items,
-                                scratch_pool));
+      if (new_actual_props)
+        SVN_ERR(svn_wc__db_op_set_props(wc_ctx->db, target_abspath,
+                                        new_actual_props,
+                                        svn_wc__has_magic_property(prop_diff),
+                                        NULL, work_items, scratch_pool));
+      else
+        SVN_ERR(svn_wc__db_wq_add(wc_ctx->db, target_abspath, work_items,
+                                  scratch_pool));
       SVN_ERR(svn_wc__wq_run(wc_ctx->db, target_abspath,
                              cancel_func, cancel_baton,
                              scratch_pool));
     }
-
+  
   return SVN_NO_ERROR;
 }
 



Re: svn commit: r1336833 - in /subversion/trunk/subversion: include/svn_wc.h libsvn_client/merge.c libsvn_wc/deprecated.c libsvn_wc/merge.c

Posted by Hyrum K Wright <hy...@wandisco.com>.
On Thu, May 31, 2012 at 4:32 PM, Hyrum K Wright
<hy...@wandisco.com> wrote:
> On Thu, May 10, 2012 at 2:13 PM,  <rh...@apache.org> wrote:
>> Author: rhuijben
>> Date: Thu May 10 19:13:11 2012
>> New Revision: 1336833
>>
>> URL: http://svn.apache.org/viewvc?rev=1336833&view=rev
>> Log:
>> Make the text and property merge handling of 'svn merge' of a single file an
>> atomic operation by moving the handling into a single libsvn_wc call that
>> installs or doesn't install the working queue items.
>>
>> * subversion/include/svn_wc.h
>>  (svn_wc_merge5): New function.
>>  (svn_wc_merge4): Deprecate function.
>>
>> * subversion/libsvn_client/merge.c
>>  (merge_file_changed): Update caller.
>>
>> * subversion/libsvn_wc/deprecated.c
>>  (svn_wc_merge4): New function. Wraps svn_wc_merge5().
>>
>> * subversion/libsvn_wc/merge.c
>>  (svn_wc_merge4): Rename to ...
>>  (svn_wc_merge5): ... this and add support for merging properties in the same
>>    operation. At the same time avoid a few more unneeded db operations.
>>
> ...
>> Modified: subversion/trunk/subversion/libsvn_wc/merge.c
>> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/merge.c?rev=1336833&r1=1336832&r2=1336833&view=diff
>> ==============================================================================
>> --- subversion/trunk/subversion/libsvn_wc/merge.c (original)
>> +++ subversion/trunk/subversion/libsvn_wc/merge.c Thu May 10 19:13:11 2012
> ...
>> @@ -1476,7 +1476,8 @@ svn_wc__internal_merge(svn_skel_t **work
>>
>>
>>  svn_error_t *
>> -svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
>> +svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
>> +              enum svn_wc_notify_state_t *merge_props_outcome,
>>               svn_wc_context_t *wc_ctx,
>>               const char *left_abspath,
>>               const char *right_abspath,
>> @@ -1489,6 +1490,7 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
>>               svn_boolean_t dry_run,
>>               const char *diff3_cmd,
>>               const apr_array_header_t *merge_options,
>> +              apr_hash_t *original_props,
>>               const apr_array_header_t *prop_diff,
>>               svn_wc_conflict_resolver_func2_t conflict_func,
>>               void *conflict_baton,
>> @@ -1497,8 +1499,11 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
>>               apr_pool_t *scratch_pool)
>>  {
>>   const char *dir_abspath = svn_dirent_dirname(target_abspath, scratch_pool);
>> +  svn_skel_t *prop_items = NULL;
>>   svn_skel_t *work_items;
>> -  apr_hash_t *actual_props;
>> +  apr_hash_t *pristine_props = NULL;
>> +  apr_hash_t *actual_props = NULL;
>> +  apr_hash_t *new_actual_props = NULL;
>>
>>   SVN_ERR_ASSERT(svn_dirent_is_absolute(left_abspath));
>>   SVN_ERR_ASSERT(svn_dirent_is_absolute(right_abspath));
>> @@ -1508,37 +1513,86 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
>>   if (!dry_run)
>>     SVN_ERR(svn_wc__write_check(wc_ctx->db, dir_abspath, scratch_pool));
>>
>> -  /* Sanity check:  the merge target must be under revision control,
>> -   * unless the merge target is a copyfrom text, which lives in a
>> -   * temporary file and does not exist in ACTUAL yet. */
>> +  /* Sanity check:  the merge target must be a file under revision control */
>>   {
>> +    svn_wc__db_status_t status;
>>     svn_kind_t kind;
>> -    svn_boolean_t hidden;
>> -    SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, target_abspath, TRUE,
>> -                                 scratch_pool));
>> +    svn_boolean_t had_props;
>> +    svn_boolean_t props_mod;
>>
>> -    if (kind == svn_kind_unknown)
>> +    SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
>> +                                 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
>> +                                 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
>> +                                 NULL, &had_props, &props_mod, NULL, NULL,
>> +                                 NULL,
>> +                                 wc_ctx->db, target_abspath,
>> +                                 scratch_pool, scratch_pool));
>> +
>> +    if (kind != svn_kind_file || (status != svn_wc__db_status_normal
>> +                                  && status != svn_wc__db_status_added))
>>       {
>> -        *merge_outcome = svn_wc_merge_no_merge;
>> +        *merge_content_outcome = svn_wc_merge_no_merge;
>> +        if (merge_props_outcome)
>> +          *merge_props_outcome = svn_wc_merge_no_merge;
>
> There is a type mismatch here: *merge_props_outcome is an enum of type
> svn_wc_notify_state_t, but svn_wc_merge_no_merge is one of
> svn_wc_merge_outcome_t.

Bert,
Any response on this?  I'm concerned about this seemingly arbitrary
type mismatch, and the effects it could have.  This probably only work
by luck at this point...

-Hyrum


-- 

uberSVN: Apache Subversion Made Easy
http://www.uberSVN.com/

Re: svn commit: r1336833 - in /subversion/trunk/subversion: include/svn_wc.h libsvn_client/merge.c libsvn_wc/deprecated.c libsvn_wc/merge.c

Posted by Hyrum K Wright <hy...@wandisco.com>.
On Thu, May 10, 2012 at 2:13 PM,  <rh...@apache.org> wrote:
> Author: rhuijben
> Date: Thu May 10 19:13:11 2012
> New Revision: 1336833
>
> URL: http://svn.apache.org/viewvc?rev=1336833&view=rev
> Log:
> Make the text and property merge handling of 'svn merge' of a single file an
> atomic operation by moving the handling into a single libsvn_wc call that
> installs or doesn't install the working queue items.
>
> * subversion/include/svn_wc.h
>  (svn_wc_merge5): New function.
>  (svn_wc_merge4): Deprecate function.
>
> * subversion/libsvn_client/merge.c
>  (merge_file_changed): Update caller.
>
> * subversion/libsvn_wc/deprecated.c
>  (svn_wc_merge4): New function. Wraps svn_wc_merge5().
>
> * subversion/libsvn_wc/merge.c
>  (svn_wc_merge4): Rename to ...
>  (svn_wc_merge5): ... this and add support for merging properties in the same
>    operation. At the same time avoid a few more unneeded db operations.
>
...
> Modified: subversion/trunk/subversion/libsvn_wc/merge.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/merge.c?rev=1336833&r1=1336832&r2=1336833&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_wc/merge.c (original)
> +++ subversion/trunk/subversion/libsvn_wc/merge.c Thu May 10 19:13:11 2012
...
> @@ -1476,7 +1476,8 @@ svn_wc__internal_merge(svn_skel_t **work
>
>
>  svn_error_t *
> -svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
> +svn_wc_merge5(enum svn_wc_merge_outcome_t *merge_content_outcome,
> +              enum svn_wc_notify_state_t *merge_props_outcome,
>               svn_wc_context_t *wc_ctx,
>               const char *left_abspath,
>               const char *right_abspath,
> @@ -1489,6 +1490,7 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
>               svn_boolean_t dry_run,
>               const char *diff3_cmd,
>               const apr_array_header_t *merge_options,
> +              apr_hash_t *original_props,
>               const apr_array_header_t *prop_diff,
>               svn_wc_conflict_resolver_func2_t conflict_func,
>               void *conflict_baton,
> @@ -1497,8 +1499,11 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
>               apr_pool_t *scratch_pool)
>  {
>   const char *dir_abspath = svn_dirent_dirname(target_abspath, scratch_pool);
> +  svn_skel_t *prop_items = NULL;
>   svn_skel_t *work_items;
> -  apr_hash_t *actual_props;
> +  apr_hash_t *pristine_props = NULL;
> +  apr_hash_t *actual_props = NULL;
> +  apr_hash_t *new_actual_props = NULL;
>
>   SVN_ERR_ASSERT(svn_dirent_is_absolute(left_abspath));
>   SVN_ERR_ASSERT(svn_dirent_is_absolute(right_abspath));
> @@ -1508,37 +1513,86 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
>   if (!dry_run)
>     SVN_ERR(svn_wc__write_check(wc_ctx->db, dir_abspath, scratch_pool));
>
> -  /* Sanity check:  the merge target must be under revision control,
> -   * unless the merge target is a copyfrom text, which lives in a
> -   * temporary file and does not exist in ACTUAL yet. */
> +  /* Sanity check:  the merge target must be a file under revision control */
>   {
> +    svn_wc__db_status_t status;
>     svn_kind_t kind;
> -    svn_boolean_t hidden;
> -    SVN_ERR(svn_wc__db_read_kind(&kind, wc_ctx->db, target_abspath, TRUE,
> -                                 scratch_pool));
> +    svn_boolean_t had_props;
> +    svn_boolean_t props_mod;
>
> -    if (kind == svn_kind_unknown)
> +    SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
> +                                 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +                                 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +                                 NULL, &had_props, &props_mod, NULL, NULL,
> +                                 NULL,
> +                                 wc_ctx->db, target_abspath,
> +                                 scratch_pool, scratch_pool));
> +
> +    if (kind != svn_kind_file || (status != svn_wc__db_status_normal
> +                                  && status != svn_wc__db_status_added))
>       {
> -        *merge_outcome = svn_wc_merge_no_merge;
> +        *merge_content_outcome = svn_wc_merge_no_merge;
> +        if (merge_props_outcome)
> +          *merge_props_outcome = svn_wc_merge_no_merge;

There is a type mismatch here: *merge_props_outcome is an enum of type
svn_wc_notify_state_t, but svn_wc_merge_no_merge is one of
svn_wc_merge_outcome_t.

-Hyrum

>         return SVN_NO_ERROR;
>       }
>
> -    SVN_ERR(svn_wc__db_node_hidden(&hidden, wc_ctx->db, target_abspath,
> -                                   scratch_pool));
> +    if (merge_props_outcome && had_props)
> +      {
> +        SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props,
> +                                               wc_ctx->db, target_abspath,
> +                                               scratch_pool, scratch_pool));
> +      }
> +    else if (merge_props_outcome)
> +      pristine_props = apr_hash_make(scratch_pool);
>
> -    if (hidden)
> +    if (props_mod)
>       {
> -        *merge_outcome = svn_wc_merge_no_merge;
> -        return SVN_NO_ERROR;
> +        SVN_ERR(svn_wc__db_read_props(&actual_props,
> +                                      wc_ctx->db, target_abspath,
> +                                      scratch_pool, scratch_pool));
>       }
> +    else if (pristine_props)
> +      actual_props = apr_hash_copy(scratch_pool, pristine_props);
> +    else
> +      actual_props = apr_hash_make(scratch_pool);
>   }
>
> -  SVN_ERR(svn_wc__db_read_props(&actual_props, wc_ctx->db, target_abspath,
> -                                scratch_pool, scratch_pool));
> +  if (merge_props_outcome)
> +    {
> +      int i;
> +      apr_hash_t *new_pristine_props;
> +      /* The PROPCHANGES may not have non-"normal" properties in it. If entry
> +         or wc props were allowed, then the following code would install them
> +         into the BASE and/or WORKING properties(!).  */
> +      for (i = prop_diff->nelts; i--; )
> +        {
> +          const svn_prop_t *change = &APR_ARRAY_IDX(prop_diff, i, svn_prop_t);
> +
> +          if (!svn_wc_is_normal_prop(change->name))
> +            return svn_error_createf(SVN_ERR_BAD_PROP_KIND, NULL,
> +                                     _("The property '%s' may not be merged "
> +                                       "into '%s'."),
> +                                     change->name,
> +                                     svn_dirent_local_style(target_abspath,
> +                                                            scratch_pool));
> +        }
> +
> +      SVN_ERR(svn_wc__merge_props(&prop_items, merge_props_outcome,
> +                                  &new_pristine_props, &new_actual_props,
> +                                  wc_ctx->db, target_abspath, svn_kind_file,
> +                                  left_version, right_version,
> +                                  original_props, pristine_props, actual_props,
> +                                  prop_diff, FALSE /* base_merge */,
> +                                  dry_run,
> +                                  conflict_func, conflict_baton,
> +                                  cancel_func, cancel_baton,
> +                                  scratch_pool, scratch_pool));
> +    }
>
>   /* Queue all the work.  */
>   SVN_ERR(svn_wc__internal_merge(&work_items,
> -                                 merge_outcome,
> +                                 merge_content_outcome,
>                                  wc_ctx->db,
>                                  left_abspath, left_version,
>                                  right_abspath, right_version,
> @@ -1554,16 +1608,24 @@ svn_wc_merge4(enum svn_wc_merge_outcome_
>                                  cancel_func, cancel_baton,
>                                  scratch_pool, scratch_pool));
>
> +  work_items = svn_wc__wq_merge(prop_items, work_items, scratch_pool);
> +
>   /* If this isn't a dry run, then run the work!  */
>   if (!dry_run)
>     {
> -      SVN_ERR(svn_wc__db_wq_add(wc_ctx->db, target_abspath, work_items,
> -                                scratch_pool));
> +      if (new_actual_props)
> +        SVN_ERR(svn_wc__db_op_set_props(wc_ctx->db, target_abspath,
> +                                        new_actual_props,
> +                                        svn_wc__has_magic_property(prop_diff),
> +                                        NULL, work_items, scratch_pool));
> +      else
> +        SVN_ERR(svn_wc__db_wq_add(wc_ctx->db, target_abspath, work_items,
> +                                  scratch_pool));
>       SVN_ERR(svn_wc__wq_run(wc_ctx->db, target_abspath,
>                              cancel_func, cancel_baton,
>                              scratch_pool));
>     }
> -
> +
>   return SVN_NO_ERROR;
>  }
>
>
>



-- 

uberSVN: Apache Subversion Made Easy
http://www.uberSVN.com/