You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2013/01/06 03:33:39 UTC

svn commit: r1429457 [9/21] - in /subversion/branches/tree-read-api: ./ build/ build/ac-macros/ build/generator/templates/ build/win32/ contrib/server-side/svncutter/ doc/ subversion/bindings/cxxhl/include/ subversion/bindings/cxxhl/include/svncxxhl/ s...

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/props.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/props.c Sun Jan  6 02:33:34 2013
@@ -52,6 +52,7 @@
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_skel.h"
 #include "private/svn_string_private.h"
+#include "private/svn_subr_private.h"
 
 #include "wc.h"
 #include "props.h"
@@ -181,33 +182,32 @@ combine_forked_mergeinfo_props(const svn
 
 
 svn_error_t *
-svn_wc__perform_props_merge(svn_wc_notify_state_t *state,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            const svn_wc_conflict_version_t *left_version,
-                            const svn_wc_conflict_version_t *right_version,
-                            apr_hash_t *baseprops,
-                            const apr_array_header_t *propchanges,
-                            svn_boolean_t base_merge,
-                            svn_boolean_t dry_run,
-                            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)
+svn_wc_merge_props3(svn_wc_notify_state_t *state,
+                    svn_wc_context_t *wc_ctx,
+                    const char *local_abspath,
+                    const svn_wc_conflict_version_t *left_version,
+                    const svn_wc_conflict_version_t *right_version,
+                    apr_hash_t *baseprops,
+                    const apr_array_header_t *propchanges,
+                    svn_boolean_t dry_run,
+                    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)
 {
   int i;
   svn_wc__db_status_t status;
   svn_kind_t kind;
   apr_hash_t *pristine_props = NULL;
-  apr_hash_t *actual_props = NULL;
-  apr_hash_t *new_pristine_props;
+  apr_hash_t *actual_props;
   apr_hash_t *new_actual_props;
   svn_boolean_t had_props, props_mod;
   svn_boolean_t have_base;
   svn_boolean_t conflicted;
   svn_skel_t *work_items = NULL;
   svn_skel_t *conflict_skel = NULL;
+  svn_wc__db_t *db = wc_ctx->db;
 
   /* IMPORTANT: svn_wc_merge_prop_diffs relies on the fact that baseprops
      may be NULL. */
@@ -289,18 +289,17 @@ svn_wc__perform_props_merge(svn_wc_notif
     SVN_ERR(svn_wc__get_actual_props(&actual_props, db, local_abspath,
                                      scratch_pool, scratch_pool));
   else
-    actual_props = apr_hash_copy(scratch_pool, pristine_props);
+    actual_props = pristine_props;
 
   /* Note that while this routine does the "real" work, it's only
      prepping tempfiles and writing log commands.  */
   SVN_ERR(svn_wc__merge_props(&conflict_skel, state,
-                              &new_pristine_props, &new_actual_props,
-                              db, local_abspath, kind,
+                              &new_actual_props,
+                              db, local_abspath,
                               baseprops /* server_baseprops */,
                               pristine_props,
                               actual_props,
-                              propchanges, base_merge, dry_run,
-                              cancel_func, cancel_baton,
+                              propchanges,
                               scratch_pool, scratch_pool));
 
   if (dry_run)
@@ -308,6 +307,18 @@ svn_wc__perform_props_merge(svn_wc_notif
       return SVN_NO_ERROR;
     }
 
+  {
+    const char *dir_abspath;
+
+    if (kind == svn_kind_dir)
+      dir_abspath = local_abspath;
+    else
+      dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+
+    /* Verify that we're holding this directory's write lock.  */
+    SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
+  }
+
   if (conflict_skel)
     {
       svn_skel_t *work_item;
@@ -325,44 +336,18 @@ svn_wc__perform_props_merge(svn_wc_notif
       work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
     }
 
-  {
-    const char *dir_abspath;
-
-    if (kind == svn_kind_dir)
-      dir_abspath = local_abspath;
-    else
-      dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+  /* After a (not-dry-run) merge, we ALWAYS have props to save.  */
+  SVN_ERR_ASSERT(new_actual_props != NULL);
 
-    /* Verify that we're holding this directory's write lock.  */
-    SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
-
-    /* After a (not-dry-run) merge, we ALWAYS have props to save.  */
-    SVN_ERR_ASSERT(new_pristine_props != NULL && new_actual_props != NULL);
-
-/* See props.h  */
-#ifdef SVN__SUPPORT_BASE_MERGE
-    if (status == svn_wc__db_status_added)
-      SVN_ERR(svn_wc__db_temp_working_set_props(db, local_abspath,
-                                                new_base_props, scratch_pool));
-    else
-      SVN_ERR(svn_wc__db_temp_base_set_props(db, local_abspath,
-                                             new_base_props, scratch_pool));
-#else
-    if (base_merge)
-      return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-                              U_("base_merge=TRUE is no longer supported"));
-#endif
-
-    SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, new_actual_props,
-                                    svn_wc__has_magic_property(propchanges),
-                                    conflict_skel,
-                                    work_items,
-                                    scratch_pool));
+  SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, new_actual_props,
+                                  svn_wc__has_magic_property(propchanges),
+                                  conflict_skel,
+                                  work_items,
+                                  scratch_pool));
 
-    if (work_items != NULL)
-      SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
-                             scratch_pool));
-  }
+  if (work_items != NULL)
+    SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                           scratch_pool));
 
   if (conflict_skel && conflict_func)
     SVN_ERR(svn_wc__conflict_invoke_resolver(db, local_abspath, conflict_skel,
@@ -374,36 +359,6 @@ svn_wc__perform_props_merge(svn_wc_notif
 }
 
 
-svn_error_t *
-svn_wc_merge_props3(svn_wc_notify_state_t *state,
-                    svn_wc_context_t *wc_ctx,
-                    const char *local_abspath,
-                    const svn_wc_conflict_version_t *left_version,
-                    const svn_wc_conflict_version_t *right_version,
-                    apr_hash_t *baseprops,
-                    const apr_array_header_t *propchanges,
-                    svn_boolean_t dry_run,
-                    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__perform_props_merge(
-                           state,
-                           wc_ctx->db,
-                           local_abspath,
-                           left_version, right_version,
-                           baseprops,
-                           propchanges,
-                           FALSE /* base_merge */,
-                           dry_run,
-                           conflict_func, conflict_baton,
-                           cancel_func, cancel_baton,
-                           scratch_pool));
-}
-
-
 /* Generate a message to describe the property conflict among these four
    values.
 
@@ -784,32 +739,26 @@ set_prop_merge_state(svn_wc_notify_state
   *state = new_value;
 }
 
-/* Add the property with name PROPNAME to the set of ACTUAL_PROPS on
- * PATH, setting *STATE or *CONFLICT_REMAINS according to merge outcomes.
- *
- * *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,
-                      svn_wc__db_t *db,
-                      const char *local_abspath,
-                      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)
@@ -818,7 +767,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
         {
@@ -848,9 +797,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;
                 }
             }
 
@@ -858,43 +806,31 @@ 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 on PATH, setting *STATE or *CONFLICT_REMAINS according to
- * merge outcomes.
- *
- * *STATE is an input and output parameter, its value is to be
- * set using set_merge_prop_state().
- *
- * BASE_VAL contains the working copy base property value
+/* Apply the deletion of a property to the existing
+ * property with value WORKING_VAL, that originally had value PRISTINE_VAL.
  *
- * 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,
-                         svn_wc__db_t *db,
-                         const char *local_abspath,
-                         apr_hash_t *actual_props,
-                         const char *propname,
+                         svn_boolean_t *did_merge,
                          const svn_string_t *base_val,
                          const svn_string_t *old_val,
-                         apr_pool_t *result_pool,
-                         apr_pool_t *scratch_pool)
+                         const svn_string_t *working_val)
 {
-  svn_string_t *working_val
-    = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING);
-
   *conflict_remains = FALSE;
 
   if (! base_val)
@@ -907,11 +843,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;
         }
     }
 
@@ -921,14 +857,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
@@ -938,29 +874,24 @@ apply_single_prop_delete(svn_wc_notify_s
 }
 
 
-/* Merge a change to the mergeinfo property. The same as
-   apply_single_prop_change(), except that the PROPNAME is always
+/* Merge a change to the mergeinfo property. Similar to
+   apply_single_prop_change(), except that the property name is always
    SVN_PROP_MERGEINFO. */
 /* ### This function is extracted straight from the previous all-in-one
    version of apply_single_prop_change() by removing the code paths that
    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,
-                                   svn_wc__db_t *db,
-                                   const char *local_abspath,
-                                   apr_hash_t *actual_props,
-                                   const char *propname,
+                                   svn_boolean_t *did_merge,
                                    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
@@ -971,24 +902,22 @@ 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
-                     deltas between base <-> WC, and base <->
-                     incoming.  Combine those deltas, and apply
-                     them to base to get the new value. */
-                  SVN_ERR(combine_forked_mergeinfo_props(&new_val, old_val,
-                                                         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);
+              /* We have base, WC, and new values.  Discover
+                 deltas between base <-> WC, and base <->
+                 incoming.  Combine those deltas, and apply
+                 them to base to get the new value. */
+              SVN_ERR(combine_forked_mergeinfo_props(&new_val, old_val,
+                                                     working_val,
+                                                     new_val,
+                                                     result_pool,
+                                                     scratch_pool));
+              *result_val = new_val;
+              *did_merge = TRUE;
             }
         }
-
       else
         {
           /* There is a base_val but no working_val */
@@ -999,39 +928,36 @@ apply_single_mergeinfo_prop_change(svn_w
   else if (! working_val) /* means !working_val && !base_val due
                              to conditions above: no prop at all */
     {
-          /* Discover any mergeinfo additions in the
-             incoming value relative to the base, and
-             "combine" those with the empty WC value. */
-          svn_mergeinfo_t deleted_mergeinfo, added_mergeinfo;
-          svn_string_t *mergeinfo_string;
-
-          SVN_ERR(diff_mergeinfo_props(&deleted_mergeinfo,
-                                       &added_mergeinfo,
-                                       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);
+      /* Discover any mergeinfo additions in the
+         incoming value relative to the base, and
+         "combine" those with the empty WC value. */
+      svn_mergeinfo_t deleted_mergeinfo, added_mergeinfo;
+      svn_string_t *mergeinfo_string;
+
+      SVN_ERR(diff_mergeinfo_props(&deleted_mergeinfo,
+                                   &added_mergeinfo,
+                                   old_val, new_val, scratch_pool));
+      SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string,
+                                      added_mergeinfo, result_pool));
+      *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
-                 deltas between base <-> WC, and base <->
-                 incoming.  Combine those deltas, and apply
-                 them to base to get the new value. */
-              SVN_ERR(combine_forked_mergeinfo_props(&new_val, old_val,
-                                                     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);
+          /* We have base, WC, and new values.  Discover
+             deltas between base <-> WC, and base <->
+             incoming.  Combine those deltas, and apply
+             them to base to get the new value. */
+          SVN_ERR(combine_forked_mergeinfo_props(&new_val, old_val,
+                                                 working_val,
+                                                 new_val, result_pool,
+                                                 scratch_pool));
+          *result_val = new_val;
+          *did_merge = TRUE;
         }
     }
 
@@ -1045,21 +971,13 @@ 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,
-                                 svn_wc__db_t *db,
-                                 const char *local_abspath,
-                                 apr_hash_t *actual_props,
-                                 const char *propname,
-                                 const svn_string_t *base_val,
+                                 svn_boolean_t *did_merge,
                                  const svn_string_t *old_val,
                                  const svn_string_t *new_val,
-                                 apr_pool_t *result_pool,
-                                 apr_pool_t *scratch_pool)
+                                 const svn_string_t *working_val)
 {
-  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
@@ -1069,14 +987,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
     {
@@ -1087,11 +1005,8 @@ apply_single_generic_prop_change(svn_wc_
   return SVN_NO_ERROR;
 }
 
-/* Change the property with name PROPNAME in the set of ACTUAL_PROPS
- * on PATH, 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_prop_merge_state(). (May be null.).
+/* Change the property with name PROPNAME, setting *RESULT_VAL,
+ * *CONFLICT_REMAINS and *DID_MERGE according to the merge outcome.
  *
  * BASE_VAL contains the working copy base property value. (May be null.)
  *
@@ -1099,17 +1014,18 @@ apply_single_generic_prop_change(svn_wc_
  * thinks it's overwriting. (Not null.)
  *
  * NEW_VAL contains the value to be set. (Not null.)
+ *
+ * WORKING_VAL contains the working copy actual value. (May be 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,
-                         svn_wc__db_t *db,
-                         const char *local_abspath,
-                         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)
 {
@@ -1132,14 +1048,13 @@ 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,
-                                                            db, local_abspath,
-                                                            actual_props,
-                                                            propname,
+                                                            did_merge,
                                                             base_val,
                                                             old_val,
                                                             new_val,
+                                                            working_val,
                                                             result_pool,
                                                             scratch_pool);
        if (err)
@@ -1160,12 +1075,9 @@ 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,
-                                               db, local_abspath,
-                                               actual_props,
-                                               propname, base_val, old_val,
-                                               new_val,
-                                               result_pool, scratch_pool));
+      SVN_ERR(apply_single_generic_prop_change(result_val, conflict_remains,
+                                               did_merge,
+                                               old_val, new_val, working_val));
     }
 
   return SVN_NO_ERROR;
@@ -1175,40 +1087,28 @@ apply_single_prop_change(svn_wc_notify_s
 svn_error_t *
 svn_wc__merge_props(svn_skel_t **conflict_skel,
                     svn_wc_notify_state_t *state,
-                    apr_hash_t **new_pristine_props,
                     apr_hash_t **new_actual_props,
                     svn_wc__db_t *db,
                     const char *local_abspath,
-                    svn_kind_t kind,
                     apr_hash_t *server_baseprops,
                     apr_hash_t *pristine_props,
                     apr_hash_t *actual_props,
                     const apr_array_header_t *propchanges,
-                    svn_boolean_t base_merge,
-                    svn_boolean_t dry_run,
-                    svn_cancel_func_t cancel_func,
-                    void *cancel_baton,
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool;
   int i;
   apr_hash_t *conflict_props = NULL;
-  apr_hash_t *old_actual_props;
   apr_hash_t *their_props;
 
   SVN_ERR_ASSERT(pristine_props != NULL);
   SVN_ERR_ASSERT(actual_props != NULL);
 
-  /* Just copy the pointers as we copy the data in the skel if
-     necessary */
-  old_actual_props = apr_hash_copy(scratch_pool, actual_props);
-
-  *new_pristine_props = NULL;
-  *new_actual_props = NULL;
+  *new_actual_props = apr_hash_copy(result_pool, actual_props);
 
   if (!server_baseprops)
-    server_baseprops = apr_hash_copy(scratch_pool, pristine_props);
+    server_baseprops = pristine_props;
 
   their_props = apr_hash_copy(scratch_pool, server_baseprops);
 
@@ -1225,59 +1125,57 @@ svn_wc__merge_props(svn_skel_t **conflic
   iterpool = svn_pool_create(scratch_pool);
   for (i = 0; i < propchanges->nelts; i++)
     {
-      const char *propname;
+      const svn_prop_t *incoming_change
+        = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
+      const char *propname = incoming_change->name;
+      const svn_string_t *base_val  /* Pristine in WC */
+        = apr_hash_get(pristine_props, propname, APR_HASH_KEY_STRING);
+      const svn_string_t *from_val  /* Merge left */
+        = apr_hash_get(server_baseprops, propname, APR_HASH_KEY_STRING);
+      const svn_string_t *to_val    /* Merge right */
+        = incoming_change->value;
+      const svn_string_t *working_val  /* Mine */
+        = apr_hash_get(actual_props, propname, APR_HASH_KEY_STRING);
+      const svn_string_t *result_val;
       svn_boolean_t conflict_remains;
-      const svn_prop_t *incoming_change;
-      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 */
+      svn_boolean_t did_merge = FALSE;
 
       svn_pool_clear(iterpool);
 
-      /* Should we stop the prop merging process?  */
-      if (cancel_func)
-        SVN_ERR(cancel_func(cancel_baton));
-
-      /* For the incoming propchange, figure out the TO and FROM values. */
-      incoming_change = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
-      propname = incoming_change->name;
-      to_val = incoming_change->value
-        ? svn_string_dup(incoming_change->value, result_pool) : NULL;
-      from_val = apr_hash_get(server_baseprops, propname, APR_HASH_KEY_STRING);
-
-      base_val = apr_hash_get(pristine_props, propname, APR_HASH_KEY_STRING);
-
-      if (base_merge)
-        apr_hash_set(pristine_props, propname, APR_HASH_KEY_STRING, to_val);
+      to_val = to_val ? svn_string_dup(to_val, result_pool) : NULL;
 
       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,
-                                      db, local_abspath,
-                                      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,
-                                         db, local_abspath,
-                                         actual_props,
-                                         propname, base_val, from_val,
-                                         result_pool, iterpool));
+        SVN_ERR(apply_single_prop_delete(&result_val, &conflict_remains,
+                                         &did_merge,
+                                         base_val, from_val, working_val));
 
       else  /* changing an existing property */
-        SVN_ERR(apply_single_prop_change(state, &conflict_remains,
-                                         db, local_abspath,
-                                         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.  */
@@ -1286,14 +1184,10 @@ svn_wc__merge_props(svn_skel_t **conflic
         {
           set_prop_merge_state(state, svn_wc_notify_state_conflicted);
 
-          if (dry_run)
-            continue;   /* skip to next incoming change */
-
           if (!conflict_props)
-            conflict_props = apr_hash_make(result_pool);
+            conflict_props = apr_hash_make(scratch_pool);
 
-          apr_hash_set(conflict_props, apr_pstrdup(result_pool, propname),
-                       APR_HASH_KEY_STRING, "");
+          apr_hash_set(conflict_props, propname, APR_HASH_KEY_STRING, "");
         }
 
     }  /* foreach propchange ... */
@@ -1301,12 +1195,6 @@ svn_wc__merge_props(svn_skel_t **conflic
 
   /* Finished applying all incoming propchanges to our hashes! */
 
-  if (dry_run)
-    return SVN_NO_ERROR;
-
-  *new_pristine_props = pristine_props;
-  *new_actual_props = actual_props;
-
   if (conflict_props != NULL)
     {
       /* Ok, we got some conflict. Lets store all the property knowledge we
@@ -1318,7 +1206,7 @@ svn_wc__merge_props(svn_skel_t **conflic
       SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(*conflict_skel,
                                                       db, local_abspath,
                                                       NULL /* reject_path */,
-                                                      old_actual_props,
+                                                      actual_props,
                                                       server_baseprops,
                                                       their_props,
                                                       conflict_props,
@@ -1663,12 +1551,15 @@ validate_prop_against_node_kind(const ch
 
 
 struct getter_baton {
+  const svn_string_t *mime_type;
   const char *local_abspath;
-  svn_wc__db_t *db;
 };
 
 
-/* */
+/* Provide the MIME_TYPE and/or push the content to STREAM for the file
+ * referenced by (getter_baton *) BATON.
+ *
+ * Implements svn_wc_canonicalize_svn_prop_get_file_t. */
 static svn_error_t *
 get_file_for_validation(const svn_string_t **mime_type,
                         svn_stream_t *stream,
@@ -1678,18 +1569,15 @@ get_file_for_validation(const svn_string
   struct getter_baton *gb = baton;
 
   if (mime_type)
-    SVN_ERR(svn_wc__internal_propget(mime_type, gb->db, gb->local_abspath,
-                                     SVN_PROP_MIME_TYPE, pool, pool));
+    *mime_type = gb->mime_type;
 
   if (stream)
     {
       svn_stream_t *read_stream;
 
-      /* Open PATH. */
+      /* Copy the text of GB->LOCAL_ABSPATH into STREAM. */
       SVN_ERR(svn_stream_open_readonly(&read_stream, gb->local_abspath,
                                        pool, pool));
-
-      /* Copy from the file into the translating stream. */
       SVN_ERR(svn_stream_copy3(read_stream, svn_stream_disown(stream, pool),
                                NULL, NULL, pool));
     }
@@ -1698,7 +1586,16 @@ get_file_for_validation(const svn_string
 }
 
 
-/* */
+/* Validate that a file has a 'non-binary' MIME type and contains
+ * self-consistent line endings.  If not, then return an error.
+ *
+ * Call GETTER (which must not be NULL) with GETTER_BATON to get the
+ * file's MIME type and/or content.  If the MIME type is non-null and
+ * is categorized as 'binary' then return an error and do not request
+ * the file content.
+ *
+ * Use PATH (a local path or a URL) only for error messages.
+ */
 static svn_error_t *
 validate_eol_prop_against_file(const char *path,
                                svn_wc_canonicalize_svn_prop_get_file_t getter,
@@ -1732,17 +1629,14 @@ validate_eol_prop_against_file(const cha
 
   err = getter(NULL, translating_stream, getter_baton, pool);
 
-  if (!err)
-    err = svn_stream_close(translating_stream);
+  err = svn_error_compose_create(err, svn_stream_close(translating_stream));
 
   if (err && err->apr_err == SVN_ERR_IO_INCONSISTENT_EOL)
     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, err,
                              _("File '%s' has inconsistent newlines"),
                              path_display);
-  else if (err)
-    return err;
 
-  return SVN_NO_ERROR;
+  return svn_error_trace(err);
 }
 
 static svn_error_t *
@@ -1763,6 +1657,10 @@ do_propset(svn_wc__db_t *db,
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
+  SVN_ERR_W(svn_wc__db_read_props(&prophash, db, local_abspath,
+                                  scratch_pool, scratch_pool),
+            _("Failed to load current properties"));
+
   /* Setting an inappropriate property is not allowed (unless
      overridden by 'skip_checks', in some circumstances).  Deleting an
      inappropriate property is allowed, however, since older clients
@@ -1773,8 +1671,9 @@ do_propset(svn_wc__db_t *db,
       const svn_string_t *new_value;
       struct getter_baton gb;
 
+      gb.mime_type = apr_hash_get(prophash,
+                                  SVN_PROP_MIME_TYPE, APR_HASH_KEY_STRING);
       gb.local_abspath = local_abspath;
-      gb.db = db;
 
       SVN_ERR(svn_wc_canonicalize_svn_prop(&new_value, name, value,
                                            local_abspath, kind,
@@ -1792,10 +1691,6 @@ do_propset(svn_wc__db_t *db,
                                                scratch_pool, scratch_pool));
     }
 
-  SVN_ERR_W(svn_wc__db_read_props(&prophash, db, local_abspath,
-                                  scratch_pool, scratch_pool),
-            _("Failed to load current properties"));
-
   /* If we're changing this file's list of expanded keywords, then
    * we'll need to invalidate its text timestamp, since keyword
    * expansion affects the comparison of working file to text base.
@@ -1830,17 +1725,17 @@ do_propset(svn_wc__db_t *db,
                                      scratch_pool))
         {
           /* If the keywords have changed, then the translation of the file
-             may be different. We should invalidate the cached TRANSLATED_SIZE
-             and LAST_MOD_TIME on this node.
+             may be different. We should invalidate the RECORDED_SIZE
+             and RECORDED_TIME on this node.
 
              Note that we don't immediately re-translate the file. But a
              "has it changed?" check in the future will do a translation
              from the pristine, and it will want to compare the (new)
-             resulting TRANSLATED_SIZE against the working copy file.
+             resulting RECORDED_SIZE against the working copy file.
 
              Also, when this file is (de)translated with the new keywords,
              then it could be different, relative to the pristine. We want
-             to ensure the LAST_MOD_TIME is different, to indicate that
+             to ensure the RECORDED_TIME is different, to indicate that
              a full detranslate/compare is performed.  */
           clear_recorded_info = TRUE;
         }
@@ -1934,7 +1829,7 @@ propset_walk_cb(const char *local_abspat
   err = do_propset(wb->db, local_abspath, kind, wb->propname, wb->propval,
                    wb->force, wb->notify_func, wb->notify_baton, scratch_pool);
   if (err && (err->apr_err == SVN_ERR_ILLEGAL_TARGET
-              || err->apr_err == SVN_ERR_WC_INVALID_SCHEDULE))
+              || err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS))
     {
       svn_error_clear(err);
       err = SVN_NO_ERROR;
@@ -1958,9 +1853,8 @@ svn_wc_prop_set4(svn_wc_context_t *wc_ct
                  apr_pool_t *scratch_pool)
 {
   enum svn_prop_kind prop_kind = svn_property_kind2(name);
-  svn_wc__db_status_t status;
   svn_kind_t kind;
-  const char *dir_abspath;
+  svn_wc__db_t *db = wc_ctx->db;
 
   /* we don't do entry properties here */
   if (prop_kind == svn_prop_entry_kind)
@@ -1975,38 +1869,34 @@ svn_wc_prop_set4(svn_wc_context_t *wc_ct
                                         name, value, scratch_pool));
     }
 
+  SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, FALSE, FALSE,
+                               scratch_pool));
+
   /* We have to do this little DIR_ABSPATH dance for backwards compat.
      But from 1.7 onwards, all locks are of infinite depth, and from 1.6
      backward we never call this API with depth > empty, so we only need
      to do the write check once per call, here (and not for every node in
-     the node walker). */
-    /* Get the node status for this path. */
-  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, NULL, NULL, NULL, NULL, NULL,
-                               wc_ctx->db, local_abspath,
-                               scratch_pool, scratch_pool));
+     the node walker).
 
-  if (status != svn_wc__db_status_normal
-      && status != svn_wc__db_status_added
-      && status != svn_wc__db_status_incomplete)
-    return svn_error_createf(SVN_ERR_WC_INVALID_SCHEDULE, NULL,
-                             _("Can't set properties on '%s':"
-                               " invalid status for updating properties."),
-                             svn_dirent_local_style(local_abspath,
-                                                    scratch_pool));
+     ### Note that we could check for a write lock on local_abspath first
+     ### if we would want to. And then justy check for kind if that fails.
+     ### ... but we need kind for the "svn:" property checks anyway */
+  {
+    const char *dir_abspath;
 
-  if (kind == svn_kind_dir)
-    dir_abspath = local_abspath;
-  else
-    dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+    if (kind == svn_kind_dir)
+      dir_abspath = local_abspath;
+    else
+      dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
-  SVN_ERR(svn_wc__write_check(wc_ctx->db, dir_abspath, scratch_pool));
+    /* Verify that we're holding this directory's write lock.  */
+    SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
+  }
 
   if (depth == svn_depth_empty || kind != svn_kind_dir)
     {
       apr_hash_t *changelist_hash = NULL;
+      svn_error_t *err;
 
       if (changelist_filter && changelist_filter->nelts)
         SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
@@ -2016,12 +1906,23 @@ svn_wc_prop_set4(svn_wc_context_t *wc_ct
                                              changelist_hash, scratch_pool))
         return SVN_NO_ERROR;
 
-      SVN_ERR(do_propset(wc_ctx->db, local_abspath,
+      err = do_propset(wc_ctx->db, local_abspath,
                          kind == svn_kind_dir
                             ? svn_node_dir
                             : svn_node_file,
                          name, value, skip_checks,
-                         notify_func, notify_baton, scratch_pool));
+                         notify_func, notify_baton, scratch_pool);
+
+      if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+        {
+          err = svn_error_createf(SVN_ERR_WC_INVALID_SCHEDULE, err,
+                                  _("Can't set properties on '%s':"
+                                  " invalid status for updating properties."),
+                                  svn_dirent_local_style(local_abspath,
+                                                         scratch_pool));
+        }
+
+      SVN_ERR(err);
     }
   else
     {
@@ -2045,6 +1946,83 @@ svn_wc_prop_set4(svn_wc_context_t *wc_ct
   return SVN_NO_ERROR;
 }
 
+/* Check that NAME names a regular prop. Return an error if it names an
+ * entry prop or a WC prop. */
+static svn_error_t *
+ensure_prop_is_regular_kind(const char *name)
+{
+  enum svn_prop_kind prop_kind = svn_property_kind2(name);
+
+  /* we don't do entry properties here */
+  if (prop_kind == svn_prop_entry_kind)
+    return svn_error_createf(SVN_ERR_BAD_PROP_KIND, NULL,
+                             _("Property '%s' is an entry property"), name);
+
+  /* Check to see if we're setting the dav cache. */
+  if (prop_kind == svn_prop_wc_kind)
+    return svn_error_createf(SVN_ERR_BAD_PROP_KIND, NULL,
+                             _("Property '%s' is a WC property, not "
+                               "a regular property"), name);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__canonicalize_props(apr_hash_t **prepared_props,
+                           const char *local_abspath,
+                           svn_node_kind_t node_kind,
+                           const apr_hash_t *props,
+                           svn_boolean_t skip_some_checks,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  const svn_string_t *mime_type;
+  struct getter_baton gb;
+  apr_hash_index_t *hi;
+
+  /* While we allocate new parts of *PREPARED_PROPS in RESULT_POOL, we
+     don't promise to deep-copy the unchanged keys and values. */
+  *prepared_props = apr_hash_make(result_pool);
+
+  /* Before we can canonicalize svn:eol-style we need to know svn:mime-type,
+   * so process that first. */
+  mime_type = apr_hash_get((apr_hash_t *)props,
+                           SVN_PROP_MIME_TYPE, APR_HASH_KEY_STRING);
+  if (mime_type)
+    {
+      SVN_ERR(svn_wc_canonicalize_svn_prop(
+                &mime_type, SVN_PROP_MIME_TYPE, mime_type,
+                local_abspath, node_kind, skip_some_checks,
+                NULL, NULL, scratch_pool));
+      apr_hash_set(*prepared_props, SVN_PROP_MIME_TYPE, APR_HASH_KEY_STRING,
+                   mime_type);
+    }
+
+  /* Set up the context for canonicalizing the other properties. */
+  gb.mime_type = mime_type;
+  gb.local_abspath = local_abspath;
+
+  /* Check and canonicalize the other properties. */
+  for (hi = apr_hash_first(scratch_pool, (apr_hash_t *)props); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      const svn_string_t *value = svn__apr_hash_index_val(hi);
+
+      if (strcmp(name, SVN_PROP_MIME_TYPE) == 0)
+        continue;
+
+      SVN_ERR(ensure_prop_is_regular_kind(name));
+      SVN_ERR(svn_wc_canonicalize_svn_prop(
+                &value, name, value,
+                local_abspath, node_kind, skip_some_checks,
+                get_file_for_validation, &gb, scratch_pool));
+      apr_hash_set(*prepared_props, name, APR_HASH_KEY_STRING, value);
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 svn_error_t *
 svn_wc_canonicalize_svn_prop(const svn_string_t **propval_p,

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/props.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/props.h?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/props.h (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/props.h Sun Jan  6 02:33:34 2013
@@ -37,18 +37,6 @@
 extern "C" {
 #endif /* __cplusplus */
 
-/* BASE_MERGE is a pre-1.7 concept on property merging. It allowed callers
-   to alter the pristine properties *outside* of an editor drive. That is
-   very dangerous: the pristines should always correspond to something from
-   the repository, and that should only arrive through the update editor.
-
-   For 1.7, we're removing this support. Some old code is being left around
-   in case we decide to change this.
-
-   For more information, see ^/notes/api-errata/1.7/wc006.txt
-*/
-#undef SVN__SUPPORT_BASE_MERGE
-
 /* Internal function for diffing props. See svn_wc_get_prop_diffs2(). */
 svn_error_t *
 svn_wc__internal_propdiff(apr_array_header_t **propchanges,
@@ -68,49 +56,59 @@ svn_wc__internal_propget(const svn_strin
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/* Validate and canonicalize the PROPS like svn_wc_prop_set4() does;
+ * see that function for details of the SKIP_SOME_CHECKS option.
+ *
+ * The properties are checked against the node at LOCAL_ABSPATH (which
+ * need not be under version control) of kind KIND.  This text of this
+ * node may be read (if it is a file) in order to validate the
+ * svn:eol-style property.
+ *
+ * Only regular props are accepted; WC props and entry props raise an error
+ * (unlike svn_wc_prop_set4() which accepts WC props).
+ *
+ * Set *PREPARED_PROPS to the resulting canonicalized properties,
+ * allocating any new data in RESULT_POOL but making shallow copies of
+ * keys and unchanged values from PROPS.
+ */
+svn_error_t *
+svn_wc__canonicalize_props(apr_hash_t **prepared_props,
+                           const char *local_abspath,
+                           svn_node_kind_t node_kind,
+                           const apr_hash_t *props,
+                           svn_boolean_t skip_some_checks,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
+
 
 /* Given LOCAL_ABSPATH/DB and an array of PROPCHANGES based on
    SERVER_BASEPROPS, calculate what changes should be applied to the working
    copy.
 
-   Return working queue operations in WORK_ITEMS and a new set of actual
-   (NEW_ACTUAL_PROPS) and pristine properties (NEW_PRISTINE_PROPS).
-
    We return the new property collections to the caller, so the caller
    can combine the property update with other operations.
 
    If SERVER_BASEPROPS is NULL then use the pristine props as PROPCHANGES
    base.
 
-   If BASE_MERGE is FALSE then only change working properties; if TRUE,
-   change both the pristine and working properties. (Only the update editor
-   should use BASE_MERGE is TRUE)
-
-   If conflicts are found when merging, create a temporary .prej file,
-   and provide working queue operations to write the conflict information
-   into the .prej file later. Modify base properties unconditionally,
-   if BASE_MERGE is TRUE, they do not generate conficts.
+   Return the new set of actual properties in *NEW_ACTUAL_PROPS.
 
-   TODO ### DRY_RUN ...
+   Append any conflicts of the actual props to *CONFLICT_SKEL.  (First
+   allocate *CONFLICT_SKEL from RESULT_POOL if it is initially NULL.
+   CONFLICT_SKEL itself must not be NULL.)
 
    If STATE is non-null, set *STATE to the state of the local properties
    after the merge.  */
 svn_error_t *
 svn_wc__merge_props(svn_skel_t **conflict_skel,
                     svn_wc_notify_state_t *state,
-                    apr_hash_t **new_pristine_props,
                     apr_hash_t **new_actual_props,
                     svn_wc__db_t *db,
                     const char *local_abspath,
-                    svn_kind_t kind,
-                    apr_hash_t *server_baseprops,
-                    apr_hash_t *pristine_props,
-                    apr_hash_t *actual_props,
+                    /*const*/ apr_hash_t *server_baseprops,
+                    /*const*/ apr_hash_t *pristine_props,
+                    /*const*/ apr_hash_t *actual_props,
                     const apr_array_header_t *propchanges,
-                    svn_boolean_t base_merge,
-                    svn_boolean_t dry_run,
-                    svn_cancel_func_t cancel_func,
-                    void *cancel_baton,
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool);
 
@@ -143,24 +141,6 @@ svn_wc__create_prejfile(const char **tmp
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool);
 
-
-/* Just like svn_wc_merge_props3(), but WITH a BASE_MERGE parameter.  */
-svn_error_t *
-svn_wc__perform_props_merge(svn_wc_notify_state_t *state,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            const svn_wc_conflict_version_t *left_version,
-                            const svn_wc_conflict_version_t *right_version,
-                            apr_hash_t *baseprops,
-                            const apr_array_header_t *propchanges,
-                            svn_boolean_t base_merge,
-                            svn_boolean_t dry_run,
-                            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);
-
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/relocate.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/relocate.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/relocate.c Sun Jan  6 02:33:34 2013
@@ -94,8 +94,8 @@ svn_wc_relocate4(svn_wc_context_t *wc_ct
   const char *uuid;
   svn_boolean_t is_wc_root;
 
-  SVN_ERR(svn_wc__strictly_is_wc_root(&is_wc_root, wc_ctx, local_abspath,
-                                      scratch_pool));
+  SVN_ERR(svn_wc__is_wcroot(&is_wc_root, wc_ctx, local_abspath,
+                            scratch_pool));
   if (! is_wc_root)
     {
       const char *wcroot_abspath;

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/status.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/status.c Sun Jan  6 02:33:34 2013
@@ -261,7 +261,7 @@ read_info(const struct svn_wc__db_info_t
                                &mtb->changed_author, &mtb->depth,
                                &checksum, NULL, &original_repos_relpath, NULL,
                                NULL, NULL, &mtb->lock, &mtb->recorded_size,
-                               &mtb->recorded_mod_time, &mtb->changelist,
+                               &mtb->recorded_time, &mtb->changelist,
                                &mtb->conflicted, &mtb->op_root,
                                &mtb->had_props, &mtb->props_mod,
                                &mtb->have_base, &mtb->have_more_work, NULL,
@@ -286,7 +286,7 @@ read_info(const struct svn_wc__db_info_t
 
       SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
                                        NULL, NULL, NULL, NULL, NULL, NULL,
-                                       lock_arg, NULL, &update_root,
+                                       lock_arg, NULL, NULL, &update_root,
                                        db, local_abspath,
                                        result_pool, scratch_pool));
 
@@ -621,9 +621,9 @@ assemble_status(svn_wc_status3_t **statu
           else if (ignore_text_mods
                   ||(dirent
                      && info->recorded_size != SVN_INVALID_FILESIZE
-                     && info->recorded_mod_time != 0
+                     && info->recorded_time != 0
                      && info->recorded_size == dirent->filesize
-                     && info->recorded_mod_time == dirent->mtime))
+                     && info->recorded_time == dirent->mtime))
             text_modified_p = FALSE;
           else
             {

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/translate.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/translate.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/translate.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/translate.c Sun Jan  6 02:33:34 2013
@@ -368,6 +368,8 @@ svn_wc__sync_flags_with_props(svn_boolea
   svn_kind_t kind;
   svn_wc__db_lock_t *lock;
   apr_hash_t *props = NULL;
+  svn_boolean_t had_props;
+  svn_boolean_t props_mod;
 
   if (did_set)
     *did_set = FALSE;
@@ -378,18 +380,25 @@ svn_wc__sync_flags_with_props(svn_boolea
   SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, &lock, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL,
+                               &had_props, &props_mod, NULL, NULL, NULL,
                                db, local_abspath,
                                scratch_pool, scratch_pool));
 
-  SVN_ERR(svn_wc__db_read_props(&props, db, local_abspath, scratch_pool,
-                                scratch_pool));
-
   /* We actually only care about the following flags on files, so just
-     early-out for all other types. */
-  if (kind != svn_kind_file)
+     early-out for all other types.
+
+     Also bail if there is no in-wc representation of the file. */
+  if (kind != svn_kind_file
+      || (status != svn_wc__db_status_normal
+          && status != svn_wc__db_status_added))
     return SVN_NO_ERROR;
 
+  if (props_mod || had_props)
+    SVN_ERR(svn_wc__db_read_props(&props, db, local_abspath, scratch_pool,
+                                  scratch_pool));
+  else
+    props = NULL;
+
   /* If we get this far, we're going to change *something*, so just set
      the flag appropriately. */
   if (did_set)
@@ -409,8 +418,13 @@ svn_wc__sync_flags_with_props(svn_boolea
          set the file read_only just yet.  That happens upon commit. */
       apr_hash_t *pristine_props;
 
-      SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props, db, local_abspath,
-                                             scratch_pool, scratch_pool));
+      if (! props_mod)
+        pristine_props = props;
+      else if (had_props)
+        SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props, db, local_abspath,
+                                                scratch_pool, scratch_pool));
+      else
+        pristine_props = NULL;
 
       if (pristine_props
             && apr_hash_get(pristine_props,
@@ -423,9 +437,7 @@ svn_wc__sync_flags_with_props(svn_boolea
 /* Windows doesn't care about the execute bit. */
 #ifndef WIN32
 
-  if ( ( status != svn_wc__db_status_normal
-        && status != svn_wc__db_status_added )
-      || props == NULL
+  if (props == NULL
       || ! apr_hash_get(props, SVN_PROP_EXECUTABLE, APR_HASH_KEY_STRING))
     {
       /* Turn off the execute bit */

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/translate.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/translate.h?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/translate.h (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/translate.h Sun Jan  6 02:33:34 2013
@@ -103,15 +103,21 @@ void svn_wc__eol_value_from_string(const
    If a keyword is in the list, but no corresponding value is
    available, do not create a hash entry for it.  If no keywords are
    found in the list, or if there is no list, set *KEYWORDS to NULL.
+     ### THIS LOOKS WRONG -- it creates a hash entry for every recognized kw
+         and expands each missing value as an empty string or "-1" or similar.
 
    Use LOCAL_ABSPATH to expand keyword values.
 
    If WRI_ABSPATH is not NULL, retrieve the information for LOCAL_ABSPATH
    from the working copy identified by WRI_ABSPATH. Falling back to file
    external information if the file is not present as versioned node.
+     ### THIS IS NOT IMPLEMENTED -- WRI_ABSPATH is ignored
 
    If FOR_NORMALIZATION is TRUE, just return a list of keywords instead of
    calculating their intended values.
+     ### This would be better done by a separate API, since in this case
+         only the KEYWORD_LIST input parameter is needed. (And there is no
+         need to print "-1" as the revision value.)
 
    Use SCRATCH_POOL for any temporary allocations.
 */

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/update_editor.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/update_editor.c Sun Jan  6 02:33:34 2013
@@ -34,7 +34,6 @@
 
 #include "svn_types.h"
 #include "svn_pools.h"
-#include "svn_delta.h"
 #include "svn_hash.h"
 #include "svn_string.h"
 #include "svn_dirent_uri.h"
@@ -47,7 +46,6 @@
 #include "wc.h"
 #include "adm_files.h"
 #include "conflicts.h"
-#include "entries.h"
 #include "translate.h"
 #include "workqueue.h"
 
@@ -496,19 +494,6 @@ cleanup_edit_baton(void *edit_baton)
   return APR_SUCCESS;
 }
 
-/* An APR pool cleanup handler.  This is a child handler, it removes
-   the mail pool handler.
-   <stsp> mail pool?
-   <hwright> that's where the missing commit mails are going!  */
-static apr_status_t
-cleanup_edit_baton_child(void *edit_baton)
-{
-  struct edit_baton *eb = edit_baton;
-  apr_pool_cleanup_kill(eb->pool, eb, cleanup_edit_baton);
-  return APR_SUCCESS;
-}
-
-
 /* Make a new dir baton in a subpool of PB->pool. PB is the parent baton.
    If PATH and PB are NULL, this is the root directory of the edit; in this
    case, make the new dir baton in a subpool of EB->pool.
@@ -1200,7 +1185,7 @@ open_root(void *edit_baton,
                                        &db->old_repos_relpath, NULL, NULL,
                                        &db->changed_rev, &db->changed_date,
                                        &db->changed_author, &db->ambient_depth,
-                                       NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
                                        eb->db, db->local_abspath,
                                        db->pool, pool));
       db->was_incomplete = (status == svn_wc__db_status_incomplete);
@@ -1660,7 +1645,7 @@ delete_entry(const char *path,
     SVN_ERR(svn_wc__db_base_get_info(&base_status, &base_kind, &old_revision,
                                      &repos_relpath,
                                      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     NULL, NULL, NULL, NULL,
+                                     NULL, NULL, NULL, NULL, NULL,
                                      eb->db, local_abspath,
                                      scratch_pool, scratch_pool));
 
@@ -2236,7 +2221,7 @@ open_directory(const char *path,
                                      &db->old_repos_relpath, NULL, NULL,
                                      &db->changed_rev, &db->changed_date,
                                      &db->changed_author, &db->ambient_depth,
-                                     NULL, NULL, NULL, NULL, NULL,
+                                     NULL, NULL, NULL, NULL, NULL, NULL,
                                      eb->db, db->local_abspath,
                                      db->pool, pool));
 
@@ -2494,23 +2479,18 @@ close_directory(void *dir_baton,
             actual_props = base_props;
         }
 
-      /* Merge pending properties into temporary files (ignoring
-         conflicts). */
+      /* Merge pending properties. */
+      new_base_props = svn_prop__patch(base_props, regular_prop_changes,
+                                       db->pool);
       SVN_ERR_W(svn_wc__merge_props(&conflict_skel,
                                     &prop_state,
-                                    &new_base_props,
                                     &new_actual_props,
                                     eb->db,
                                     db->local_abspath,
-                                    svn_kind_dir,
                                     NULL /* use baseprops */,
                                     base_props,
                                     actual_props,
                                     regular_prop_changes,
-                                    TRUE /* base_merge */,
-                                    FALSE /* dry_run */,
-                                    eb->cancel_func,
-                                    eb->cancel_baton,
                                     db->pool,
                                     scratch_pool),
                 _("Couldn't do property merge"));
@@ -2563,7 +2543,7 @@ close_directory(void *dir_baton,
             /* ### We just check if there is some node in BASE at this path */
             err = svn_wc__db_base_get_info(&status, NULL, NULL, NULL, NULL,
                                            NULL, NULL, NULL, NULL, NULL, NULL,
-                                           NULL, NULL, NULL, NULL,
+                                           NULL, NULL, NULL, NULL, NULL,
                                            eb->db, child_abspath,
                                            iterpool, iterpool);
 
@@ -3298,7 +3278,7 @@ open_file(const char *path,
                                      &fb->changed_rev, &fb->changed_date,
                                      &fb->changed_author, NULL,
                                      &fb->original_checksum, NULL, NULL,
-                                     NULL, NULL,
+                                     NULL, NULL, NULL,
                                      eb->db, fb->local_abspath,
                                      fb->pool, scratch_pool));
 
@@ -4111,20 +4091,17 @@ close_file(void *file_baton,
       /* This will merge the old and new props into a new prop db, and
          write <cp> commands to the logfile to install the merged
          props.  */
+      new_base_props = svn_prop__patch(current_base_props, regular_prop_changes,
+                                       scratch_pool);
       SVN_ERR(svn_wc__merge_props(&conflict_skel,
                                   &prop_state,
-                                  &new_base_props,
                                   &new_actual_props,
                                   eb->db,
                                   fb->local_abspath,
-                                  svn_kind_file,
                                   NULL /* server_baseprops (update, not merge)  */,
                                   current_base_props,
                                   current_actual_props,
                                   regular_prop_changes, /* propchanges */
-                                  TRUE /* base_merge */,
-                                  FALSE /* dry_run */,
-                                  eb->cancel_func, eb->cancel_baton,
                                   scratch_pool,
                                   scratch_pool));
       /* We will ALWAYS have properties to save (after a not-dry-run merge). */
@@ -4246,20 +4223,17 @@ close_file(void *file_baton,
 
       /* Store the incoming props (sent as propchanges) in new_base_props
          and create a set of new actual props to use for notifications */
+      new_base_props = svn_prop__patch(current_base_props, regular_prop_changes,
+                                       scratch_pool);
       SVN_ERR(svn_wc__merge_props(&conflict_skel,
                                   &prop_state,
-                                  &new_base_props,
                                   &new_actual_props,
                                   eb->db,
                                   fb->local_abspath,
-                                  svn_kind_file,
                                   NULL /* server_baseprops (not merging) */,
                                   current_base_props /* pristine_props */,
                                   fake_actual_props /* actual_props */,
                                   regular_prop_changes, /* propchanges */
-                                  TRUE /* base_merge */,
-                                  FALSE /* dry_run */,
-                                  eb->cancel_func, eb->cancel_baton,
                                   scratch_pool,
                                   scratch_pool));
 
@@ -4476,7 +4450,7 @@ close_edit(void *edit_baton,
              have to worry about removing it. */
           err = svn_wc__db_base_get_info(&status, NULL, NULL, NULL, NULL, NULL,
                                          NULL, NULL, NULL, NULL, NULL, NULL,
-                                         NULL, NULL, NULL,
+                                         NULL, NULL, NULL, NULL,
                                          eb->db, eb->target_abspath,
                                          scratch_pool, scratch_pool);
           if (err)
@@ -4633,7 +4607,7 @@ make_editor(svn_revnum_t *target_revisio
   eb->ext_patterns             = preserved_exts;
 
   apr_pool_cleanup_register(edit_pool, eb, cleanup_edit_baton,
-                            cleanup_edit_baton_child);
+                            apr_pool_cleanup_null);
 
   /* Construct an editor. */
   tree_editor->set_target_revision = set_target_revision;
@@ -4674,7 +4648,7 @@ make_editor(svn_revnum_t *target_revisio
       err = svn_wc__db_base_get_info(&dir_status, &dir_kind, NULL,
                                      &dir_repos_relpath, NULL, NULL, NULL,
                                      NULL, NULL, &dir_depth, NULL, NULL, NULL,
-                                     NULL, NULL,
+                                     NULL, NULL, NULL,
                                      db, eb->target_abspath,
                                      scratch_pool, scratch_pool);
 
@@ -4730,7 +4704,7 @@ make_editor(svn_revnum_t *target_revisio
                                                    NULL, &dir_repos_relpath,
                                                    NULL, NULL, NULL, NULL,
                                                    NULL, &dir_depth, NULL,
-                                                   NULL, NULL, NULL,
+                                                   NULL, NULL, NULL, NULL,
                                                    NULL,
                                                    db, child_abspath,
                                                    iterpool, iterpool));
@@ -4904,207 +4878,6 @@ svn_wc__get_switch_editor(const svn_delt
                      result_pool, scratch_pool);
 }
 
-/* ABOUT ANCHOR AND TARGET, AND svn_wc_get_actual_target2()
-
-   THE GOAL
-
-   Note the following actions, where X is the thing we wish to update,
-   P is a directory whose repository URL is the parent of
-   X's repository URL, N is directory whose repository URL is *not*
-   the parent directory of X (including the case where N is not a
-   versioned resource at all):
-
-      1.  `svn up .' from inside X.
-      2.  `svn up ...P/X' from anywhere.
-      3.  `svn up ...N/X' from anywhere.
-
-   For the purposes of the discussion, in the '...N/X' situation, X is
-   said to be a "working copy (WC) root" directory.
-
-   Now consider the four cases for X's type (file/dir) in the working
-   copy vs. the repository:
-
-      A.  dir in working copy, dir in repos.
-      B.  dir in working copy, file in repos.
-      C.  file in working copy, dir in repos.
-      D.  file in working copy, file in repos.
-
-   Here are the results we expect for each combination of the above:
-
-      1A. Successfully update X.
-      1B. Error (you don't want to remove your current working
-          directory out from underneath the application).
-      1C. N/A (you can't be "inside X" if X is a file).
-      1D. N/A (you can't be "inside X" if X is a file).
-
-      2A. Successfully update X.
-      2B. Successfully update X.
-      2C. Successfully update X.
-      2D. Successfully update X.
-
-      3A. Successfully update X.
-      3B. Error (you can't create a versioned file X inside a
-          non-versioned directory).
-      3C. N/A (you can't have a versioned file X in directory that is
-          not its repository parent).
-      3D. N/A (you can't have a versioned file X in directory that is
-          not its repository parent).
-
-   To summarize, case 2 always succeeds, and cases 1 and 3 always fail
-   (or can't occur) *except* when the target is a dir that remains a
-   dir after the update.
-
-   ACCOMPLISHING THE GOAL
-
-   Updates are accomplished by driving an editor, and an editor is
-   "rooted" on a directory.  So, in order to update a file, we need to
-   break off the basename of the file, rooting the editor in that
-   file's parent directory, and then updating only that file, not the
-   other stuff in its parent directory.
-
-   Secondly, we look at the case where we wish to update a directory.
-   This is typically trivial.  However, one problematic case, exists
-   when we wish to update a directory that has been removed from the
-   repository and replaced with a file of the same name.  If we root
-   our edit at the initial directory, there is no editor mechanism for
-   deleting that directory and replacing it with a file (this would be
-   like having an editor now anchored on a file, which is disallowed).
-
-   All that remains is to have a function with the knowledge required
-   to properly decide where to root our editor, and what to act upon
-   with that now-rooted editor.  Given a path to be updated, this
-   function should conditionally split that path into an "anchor" and
-   a "target", where the "anchor" is the directory at which the update
-   editor is rooted (meaning, editor->open_root() is called with
-   this directory in mind), and the "target" is the actual intended
-   subject of the update.
-
-   svn_wc_get_actual_target2() is that function.
-
-   So, what are the conditions?
-
-   Case I: Any time X is '.' (implying it is a directory), we won't
-   lop off a basename.  So we'll root our editor at X, and update all
-   of X.
-
-   Cases II & III: Any time we are trying to update some path ...N/X,
-   we again will not lop off a basename.  We can't root an editor at
-   ...N with X as a target, either because ...N isn't a versioned
-   resource at all (Case II) or because X is X is not a child of ...N
-   in the repository (Case III).  We root at X, and update X.
-
-   Cases IV-???: We lop off a basename when we are updating a
-   path ...P/X, rooting our editor at ...P and updating X, or when X
-   is missing from disk.
-
-   These conditions apply whether X is a file or directory.
-
-   ---
-
-   As it turns out, commits need to have a similar check in place,
-   too, specifically for the case where a single directory is being
-   committed (we have to anchor at that directory's parent in case the
-   directory itself needs to be modified).
-*/
-
-
-svn_error_t *
-svn_wc__check_wc_root(svn_boolean_t *wc_root,
-                      svn_kind_t *kind,
-                      svn_boolean_t *switched,
-                      svn_wc__db_t *db,
-                      const char *local_abspath,
-                      apr_pool_t *scratch_pool)
-{
-  return svn_error_trace(
-            svn_wc__db_is_switched(wc_root, switched, kind,
-                                   db, local_abspath,
-                                   scratch_pool));
-}
-
-svn_error_t *
-svn_wc_check_root(svn_boolean_t *is_wcroot,
-                  svn_boolean_t *is_switched,
-                  svn_kind_t *kind,
-                  svn_wc_context_t *wc_ctx,
-                  const char *local_abspath,
-                  apr_pool_t *scratch_pool)
-{
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  return svn_error_trace(svn_wc__db_is_switched(is_wcroot,is_switched, kind,
-                                                wc_ctx->db, local_abspath,
-                                                scratch_pool));
-}
-
-svn_error_t*
-svn_wc__strictly_is_wc_root(svn_boolean_t *wc_root,
-                            svn_wc_context_t *wc_ctx,
-                            const char *local_abspath,
-                            apr_pool_t *scratch_pool)
-{
-  return svn_error_trace(svn_wc__db_is_wcroot(wc_root,
-                                              wc_ctx->db,
-                                              local_abspath,
-                                              scratch_pool));
-}
-
-
-svn_error_t *
-svn_wc__get_wc_root(const char **wcroot_abspath,
-                    svn_wc_context_t *wc_ctx,
-                    const char *local_abspath,
-                    apr_pool_t *result_pool,
-                    apr_pool_t *scratch_pool)
-{
-  return svn_wc__db_get_wcroot(wcroot_abspath, wc_ctx->db,
-                               local_abspath, result_pool, scratch_pool);
-}
-
-
-svn_error_t *
-svn_wc_get_actual_target2(const char **anchor,
-                          const char **target,
-                          svn_wc_context_t *wc_ctx,
-                          const char *path,
-                          apr_pool_t *result_pool,
-                          apr_pool_t *scratch_pool)
-{
-  svn_boolean_t is_wc_root, is_switched;
-  svn_kind_t kind;
-  const char *local_abspath;
-  svn_error_t *err;
-
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
-
-  err = svn_wc__check_wc_root(&is_wc_root, &kind, &is_switched,
-                              wc_ctx->db, local_abspath,
-                              scratch_pool);
-
-  if (err)
-    {
-      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND &&
-          err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
-        return svn_error_trace(err);
-
-      svn_error_clear(err);
-      is_wc_root = FALSE;
-      is_switched = FALSE;
-    }
-
-  /* If PATH is not a WC root, or if it is a file, lop off a basename. */
-  if (!(is_wc_root || is_switched) || (kind != svn_kind_dir))
-    {
-      svn_dirent_split(anchor, target, path, result_pool);
-    }
-  else
-    {
-      *anchor = apr_pstrdup(result_pool, path);
-      *target = "";
-    }
-
-  return SVN_NO_ERROR;
-}
 
 
 /* ### Note that this function is completely different from the rest of the
@@ -5339,7 +5112,7 @@ svn_wc_add_repos_file4(svn_wc_context_t 
 
     /* If new contents were provided, then we do NOT want to record the
        file information. We assume the new contents do not match the
-       "proper" values for TRANSLATED_SIZE and LAST_MOD_TIME.  */
+       "proper" values for RECORDED_SIZE and RECORDED_TIME.  */
     record_fileinfo = (new_contents == NULL);
 
     /* Install the working copy file (with appropriate translation) from

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/upgrade.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/upgrade.c Sun Jan  6 02:33:34 2013
@@ -1169,7 +1169,8 @@ bump_to_23(void *baton, svn_sqlite__db_t
   svn_sqlite__stmt_t *stmt;
   svn_boolean_t have_row;
 
-  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_HAS_WORKING_NODES));
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+                                    STMT_UPGRADE_23_HAS_WORKING_NODES));
   SVN_ERR(svn_sqlite__step(&have_row, stmt));
   SVN_ERR(svn_sqlite__reset(stmt));
   if (have_row)
@@ -1753,16 +1754,8 @@ upgrade_to_wcng(void **dir_baton,
   return SVN_NO_ERROR;
 }
 
-
-/* Return a string indicating the released version (or versions) of
- * Subversion that used WC format number WC_FORMAT, or some other
- * suitable string if no released version used WC_FORMAT.
- *
- * ### It's not ideal to encode this sort of knowledge in this low-level
- * library.  On the other hand, it doesn't need to be updated often and
- * should be easily found when it does need to be updated.  */
-static const char *
-version_string_from_format(int wc_format)
+const char *
+svn_wc__version_string_from_format(int wc_format)
 {
   switch (wc_format)
     {
@@ -1770,6 +1763,7 @@ version_string_from_format(int wc_format
       case 8: return "1.4";
       case 9: return "1.5";
       case 10: return "1.6";
+      case SVN_WC__WC_NG_VERSION: return "1.7";
     }
   return _("(unreleased development version)");
 }
@@ -1792,7 +1786,7 @@ svn_wc__upgrade_sdb(int *result_format,
                              svn_dirent_local_style(wcroot_abspath,
                                                     scratch_pool),
                              start_format,
-                             version_string_from_format(start_format));
+                             svn_wc__version_string_from_format(start_format));
 
   /* Early WCNG formats no longer supported. */
   if (start_format < 19)

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/util.c?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/util.c (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/util.c Sun Jan  6 02:33:34 2013
@@ -610,8 +610,9 @@ svn_wc__fetch_base_func(const char **fil
 
   err = svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
                                  NULL, NULL, NULL, NULL, &checksum,
-                                 NULL, NULL, NULL, NULL, sfb->db,
-                                 local_abspath, scratch_pool, scratch_pool);
+                                 NULL, NULL, NULL, NULL, NULL,
+                                 sfb->db, local_abspath,
+                                 scratch_pool, scratch_pool);
   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
     {
       svn_error_clear(err);

Modified: subversion/branches/tree-read-api/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/wc-metadata.sql?rev=1429457&r1=1429456&r2=1429457&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/wc-metadata.sql Sun Jan  6 02:33:34 2013
@@ -181,8 +181,8 @@ CREATE TABLE ACTUAL_NODE (
   PRIMARY KEY (wc_id, local_relpath)
   );
 
-CREATE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath);
-CREATE INDEX I_ACTUAL_CHANGELIST ON ACTUAL_NODE (changelist);
+CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath,
+                                                    local_relpath);
 
 
 /* ------------------------------------------------------------------------- */
@@ -253,19 +253,10 @@ PRAGMA user_version =
    op_depth values are not normally visible to the user but may become
    visible after reverting local changes.
 
-   ### The following text needs revision
-
-   Each row in BASE_NODE has an associated row NODE_DATA. Additionally, each
-   row in WORKING_NODE has one or more associated rows in NODE_DATA.
-
    This table contains full node descriptions for nodes in either the BASE
    or WORKING trees as described in notes/wc-ng/design. Fields relate
    both to BASE and WORKING trees, unless documented otherwise.
 
-   ### This table is to be integrated into the SCHEMA statement as soon
-       the experimental status of NODES is lifted.
-   ### This table superseeds NODE_DATA
-
    For illustration, with a scenario like this:
 
      # (0)
@@ -275,12 +266,11 @@ PRAGMA user_version =
      touch foo/bar
      svn add foo/bar    # (2)
 
-   , these are the NODES for the path foo/bar (before single-db, the
-   numbering of op_depth is still a bit different):
+   , these are the NODES table rows for the path foo/bar:
 
-   (0)  BASE_NODE ----->  NODES (op_depth == 0)
-   (1)                    NODES (op_depth == 1) ( <----_ )
-   (2)                    NODES (op_depth == 2)   <----- WORKING_NODE
+   (0)  "BASE" --->  NODES (op_depth == 0)
+   (1)               NODES (op_depth == 1)
+   (2)               NODES (op_depth == 2)
 
    0 is the original data for foo/bar before 'svn rm foo' (if it existed).
    1 is the data for foo/bar copied in from ^/moo/bar.
@@ -408,8 +398,11 @@ CREATE TABLE NODES (
   /* the kind of the new node. may be "unknown" if the node is not present. */
   kind  TEXT NOT NULL,
 
-  /* serialized skel of this node's properties. NULL if we
-     have no information about the properties (a non-present node). */
+  /* serialized skel of this node's properties (when presence is 'normal' or
+     'incomplete'); an empty skel or NULL indicates no properties.  NULL if
+     we have no information about the properties (any other presence).
+     TODO: Choose & require a single representation for 'no properties'.
+  */
   properties  BLOB,
 
   /* NULL depth means "default" (typically svn_depth_infinity) */
@@ -483,7 +476,8 @@ CREATE TABLE NODES (
 
   );
 
-CREATE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath, op_depth);
+CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath,
+                                             local_relpath, op_depth);
 /* I_NODES_MOVED is introduced in format 30 */
 CREATE UNIQUE INDEX I_NODES_MOVED ON NODES (wc_id, moved_to, op_depth);
 
@@ -553,7 +547,7 @@ CREATE TABLE EXTERNALS (
   /* Repository location fields */
   repos_id  INTEGER NOT NULL REFERENCES REPOSITORY (id),
 
-  /* Either 'normal' or 'excluded' */
+  /* Either MAP_NORMAL or MAP_EXCLUDED */
   presence  TEXT NOT NULL,
 
   /* the kind of the external. */
@@ -574,7 +568,6 @@ CREATE TABLE EXTERNALS (
   PRIMARY KEY (wc_id, local_relpath)
 );
 
-CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath);
 CREATE UNIQUE INDEX I_EXTERNALS_DEFINED ON EXTERNALS (wc_id,
                                                       def_local_relpath,
                                                       local_relpath);
@@ -667,6 +660,9 @@ PRAGMA user_version = 22;
 -- STMT_UPGRADE_TO_23
 PRAGMA user_version = 23;
 
+-- STMT_UPGRADE_23_HAS_WORKING_NODES
+SELECT 1 FROM nodes WHERE op_depth > 0
+LIMIT 1
 
 /* ------------------------------------------------------------------------- */
 
@@ -820,6 +816,8 @@ WHERE wc_id = ?1 and local_relpath = ?2
    inherited properties */
 -- STMT_UPGRADE_TO_31
 ALTER TABLE NODES ADD COLUMN inherited_props BLOB;
+DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST;
+DROP INDEX IF EXISTS I_EXTERNALS_PARENT;
 
 PRAGMA user_version = 31;
 
@@ -846,6 +844,23 @@ WHERE (l.local_relpath = '' AND l.repos_
                                  '/'))
 
 /* ------------------------------------------------------------------------- */
+/* Format 32 ....  */
+-- STMT_UPGRADE_TO_32
+
+/* Drop old index. ### Remove this part from the upgrade to 31 once bumped */
+DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST;
+DROP INDEX IF EXISTS I_EXTERNALS_PARENT;
+CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath);
+
+DROP INDEX I_NODES_PARENT;
+CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath,
+                                             local_relpath, op_depth);
+
+DROP INDEX I_ACTUAL_PARENT;
+CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL (wc_id, parent_relpath,
+                                               local_relpath);
+
+/* ------------------------------------------------------------------------- */
 
 /* Format YYY introduces new handling for conflict information.  */
 -- format: YYY
@@ -902,8 +917,8 @@ CREATE TABLE ACTUAL_NODE (
   PRIMARY KEY (wc_id, local_relpath)
   );
 
-CREATE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath);
-CREATE INDEX I_ACTUAL_CHANGELIST ON ACTUAL_NODE (changelist);
+CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath,
+                                                    local_relpath);
 
 INSERT INTO ACTUAL_NODE SELECT
   wc_id, local_relpath, parent_relpath, properties, conflict_old,