subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1416748 [3/5] - in /subversion/branches/ev2-export: ./ build/ac-macros/ build/generator/ subversion/bindings/cxxhl/ subversion/bindings/swig/perl/native/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/...
Date Tue, 04 Dec 2012 02:26:43 GMT
Modified: subversion/branches/ev2-export/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/diff_editor.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/diff_editor.c Tue Dec  4 02:26:18 2012
@@ -610,8 +610,8 @@ file_diff(struct edit_baton *eb,
       apr_hash_t *baseprops;
 
       /* Get svn:mime-type from pristine props (in BASE or WORKING) of PATH. */
-      SVN_ERR(svn_wc__get_pristine_props(&baseprops, db, local_abspath,
-                                         scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_read_pristine_props(&baseprops, db, local_abspath,
+                                             scratch_pool, scratch_pool));
       if (baseprops)
         base_mimetype = get_prop_mimetype(baseprops);
       else
@@ -731,8 +731,8 @@ file_diff(struct edit_baton *eb,
                          || status == svn_wc__db_status_copied
                          || status == svn_wc__db_status_moved_here);
 
-          SVN_ERR(svn_wc__get_pristine_props(&baseprops, db, local_abspath,
-                                             scratch_pool, scratch_pool));
+          SVN_ERR(svn_wc__db_read_pristine_props(&baseprops, db, local_abspath,
+                                                 scratch_pool, scratch_pool));
 
           /* baseprops will be NULL for added nodes */
           if (!baseprops)
@@ -984,8 +984,8 @@ report_wc_file_as_added(struct edit_bato
   emptyprops = apr_hash_make(scratch_pool);
 
   if (eb->use_text_base)
-    SVN_ERR(svn_wc__get_pristine_props(&wcprops, db, local_abspath,
-                                       scratch_pool, scratch_pool));
+    SVN_ERR(svn_wc__db_read_pristine_props(&wcprops, db, local_abspath,
+                                           scratch_pool, scratch_pool));
   else
     SVN_ERR(svn_wc__get_actual_props(&wcprops, db, local_abspath,
                                      scratch_pool, scratch_pool));
@@ -996,16 +996,21 @@ report_wc_file_as_added(struct edit_bato
 
 
   if (eb->use_text_base)
-    SVN_ERR(get_pristine_file(&source_file, db, local_abspath,
-                              FALSE, scratch_pool, scratch_pool));
+    {
+      SVN_ERR(get_pristine_file(&source_file, db, local_abspath,
+                                FALSE, scratch_pool, scratch_pool));
+      translated_file = source_file; /* No translation needed */
+    }
   else
-    source_file = local_abspath;
+    {
+      source_file = local_abspath;
 
-  SVN_ERR(svn_wc__internal_translated_file(
+      SVN_ERR(svn_wc__internal_translated_file(
            &translated_file, source_file, db, local_abspath,
            SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_USE_GLOBAL_TMP,
            eb->cancel_func, eb->cancel_baton,
            scratch_pool, scratch_pool));
+    }
 
   SVN_ERR(eb->callbacks->file_added(NULL, NULL, NULL,
                                     path,
@@ -1054,8 +1059,8 @@ report_wc_directory_as_added(struct edit
                                         eb->changelist_hash, scratch_pool))
     {
       if (eb->use_text_base)
-        SVN_ERR(svn_wc__get_pristine_props(&wcprops, db, local_abspath,
-                                           scratch_pool, scratch_pool));
+        SVN_ERR(svn_wc__db_read_pristine_props(&wcprops, db, local_abspath,
+                                               scratch_pool, scratch_pool));
       else
         SVN_ERR(svn_wc__get_actual_props(&wcprops, db, local_abspath,
                                          scratch_pool, scratch_pool));
@@ -1227,8 +1232,9 @@ delete_entry(const char *path,
           SVN_ERR(get_pristine_file(&textbase, db, local_abspath,
                                     eb->use_text_base, pool, pool));
 
-          SVN_ERR(svn_wc__get_pristine_props(&baseprops, eb->db, local_abspath,
-                                             pool, pool));
+          SVN_ERR(svn_wc__db_read_pristine_props(&baseprops,
+                                                 eb->db, local_abspath,
+                                                 pool, pool));
           base_mimetype = get_prop_mimetype(baseprops);
 
           SVN_ERR(eb->callbacks->file_deleted(NULL, NULL, path,
@@ -1349,9 +1355,10 @@ close_directory(void *dir_baton,
         {
           if (db->eb->use_text_base)
             {
-              SVN_ERR(svn_wc__get_pristine_props(&originalprops,
-                                                 eb->db, db->local_abspath,
-                                                 scratch_pool, scratch_pool));
+              SVN_ERR(svn_wc__db_read_pristine_props(&originalprops,
+                                                     eb->db, db->local_abspath,
+                                                     scratch_pool,
+                                                     scratch_pool));
             }
           else
             {
@@ -1362,9 +1369,9 @@ close_directory(void *dir_baton,
                                                scratch_pool, scratch_pool));
 
               /* Load the BASE and repository directory properties. */
-              SVN_ERR(svn_wc__get_pristine_props(&base_props,
-                                                 eb->db, db->local_abspath,
-                                                 scratch_pool, scratch_pool));
+              SVN_ERR(svn_wc__db_base_get_props(&base_props,
+                                                eb->db, db->local_abspath,
+                                                scratch_pool, scratch_pool));
 
               repos_props = apply_propchanges(base_props, db->propchanges);
 

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/diff_local.c Tue Dec  4 02:26:18 2012
@@ -239,8 +239,8 @@ file_diff(struct diff_baton *eb,
           /* We show a deletion of what was actually deleted */
           SVN_ERR_ASSERT(status == svn_wc__db_status_deleted);
 
-          SVN_ERR(svn_wc__get_pristine_props(&del_props, db, local_abspath,
-                                             scratch_pool, scratch_pool));
+          SVN_ERR(svn_wc__db_read_pristine_props(&del_props, db, local_abspath,
+                                                 scratch_pool, scratch_pool));
 
           SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, NULL, NULL, NULL,
                                                 NULL, &del_checksum, NULL,
@@ -513,9 +513,7 @@ diff_status_callback(void *baton,
       /* Report the prop change. */
       /* ### This case should probably be extended for git-diff, but this
              is what the old diff code provided */
-      if (status->node_status == svn_wc_status_deleted
-          || status->node_status == svn_wc_status_replaced
-          || status->prop_status == svn_wc_status_modified)
+      if (status->prop_status == svn_wc_status_modified)
         {
           apr_array_header_t *propchanges;
           apr_hash_t *baseprops;

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/externals.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/externals.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/externals.c Tue Dec  4 02:26:18 2012
@@ -164,10 +164,8 @@ svn_wc_parse_externals_description3(apr_
                                     apr_pool_t *pool)
 {
   int i;
-  unsigned int len;
   apr_array_header_t *externals = NULL;
   apr_array_header_t *lines = svn_cstring_split(desc, "\n\r", TRUE, pool);
-  apr_hash_t *duplicate_check = apr_hash_make(pool);
   const char *parent_directory_display = svn_path_is_url(parent_directory) ?
     parent_directory : svn_dirent_local_style(parent_directory, pool);
 
@@ -332,21 +330,6 @@ svn_wc_parse_externals_description3(apr_
             item->url = svn_dirent_canonicalize(item->url, pool);
         }
 
-      /* Has the same WC target path already been mentioned in this prop? */
-      len = apr_hash_count(duplicate_check);
-      apr_hash_set(duplicate_check, item->target_dir, APR_HASH_KEY_STRING, "");
-      if (len == apr_hash_count(duplicate_check))
-        {
-          /* Hashtable length is unchanged. This must be a duplicate. */
-          return svn_error_createf
-            (SVN_ERR_CLIENT_INVALID_EXTERNALS_DESCRIPTION, NULL,
-             _("Invalid %s property on '%s': "
-               "target '%s' appears more than once"),
-             SVN_PROP_EXTERNALS,
-             parent_directory_display,
-             item->target_dir);
-        }
-
       if (externals)
         APR_ARRAY_PUSH(externals, svn_wc_external_item2_t *) = item;
     }
@@ -357,6 +340,53 @@ svn_wc_parse_externals_description3(apr_
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_wc__externals_find_target_dups(apr_array_header_t **duplicate_targets,
+                                   apr_array_header_t *externals,
+                                   apr_pool_t *pool,
+                                   apr_pool_t *scratch_pool)
+{
+  int i;
+  unsigned int len;
+  unsigned int len2;
+  const char *target;
+  apr_hash_t *targets = apr_hash_make(scratch_pool);
+  apr_hash_t *targets2 = NULL;
+  *duplicate_targets = NULL;
+
+  for (i = 0; i < externals->nelts; i++)
+    {
+      target = APR_ARRAY_IDX(externals, i,
+                                         svn_wc_external_item2_t*)->target_dir;
+      len = apr_hash_count(targets);
+      apr_hash_set(targets, target, APR_HASH_KEY_STRING, "");
+      if (len == apr_hash_count(targets))
+        {
+          /* Hashtable length is unchanged. This must be a duplicate. */
+
+          /* Collapse multiple duplicates of the same target by using a second
+           * hash layer. */
+          if (! targets2)
+            targets2 = apr_hash_make(scratch_pool);
+          len2 = apr_hash_count(targets2);
+          apr_hash_set(targets2, target, APR_HASH_KEY_STRING, "");
+          if (len2 < apr_hash_count(targets2))
+            {
+              /* The second hash list just got bigger, i.e. this target has
+               * not been counted as duplicate before. */
+              if (! *duplicate_targets)
+                {
+                  *duplicate_targets = apr_array_make(
+                                    pool, 1, sizeof(svn_wc_external_item2_t*));
+                }
+              APR_ARRAY_PUSH((*duplicate_targets), const char *) = target;
+            }
+          /* Else, this same target has already been recorded as a duplicate,
+           * don't count it again. */
+        }
+    }
+  return SVN_NO_ERROR;
+}
 
 struct edit_baton
 {

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/props.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/props.c Tue Dec  4 02:26:18 2012
@@ -280,8 +280,8 @@ svn_wc__perform_props_merge(svn_wc_notif
     }
 
   if (had_props)
-    SVN_ERR(svn_wc__get_pristine_props(&pristine_props, db, local_abspath,
-                                       scratch_pool, scratch_pool));
+    SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props, db, local_abspath,
+                                           scratch_pool, scratch_pool));
   if (pristine_props == NULL)
     pristine_props = apr_hash_make(scratch_pool);
 
@@ -1513,13 +1513,13 @@ svn_wc__prop_retrieve_recursive(apr_hash
 }
 
 svn_error_t *
-svn_wc__get_pristine_props(apr_hash_t **props,
-                           svn_wc__db_t *db,
-                           const char *local_abspath,
-                           apr_pool_t *result_pool,
-                           apr_pool_t *scratch_pool)
+svn_wc_get_pristine_props(apr_hash_t **props,
+                          svn_wc_context_t *wc_ctx,
+                          const char *local_abspath,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
 {
-  svn_wc__db_status_t status;
+  svn_error_t *err;
 
   SVN_ERR_ASSERT(props != NULL);
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
@@ -1527,60 +1527,23 @@ svn_wc__get_pristine_props(apr_hash_t **
   /* Certain node stats do not have properties defined on them. Check the
      state, and return NULL for these situations.  */
 
-  SVN_ERR(svn_wc__db_read_info(&status, 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, NULL,
-                               db, local_abspath,
-                               scratch_pool, scratch_pool));
-  if (status == svn_wc__db_status_added)
-    {
-      /* Resolve the status. copied and moved_here arrive with properties,
-         while a simple add does not.  */
-      SVN_ERR(svn_wc__db_scan_addition(&status, NULL,
-                                       NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       db, local_abspath,
-                                       scratch_pool, scratch_pool));
-    }
-  if (status == svn_wc__db_status_added
-#if 0
-      /* ### the update editor needs to fetch properties while the directory
-         ### is still marked incomplete  */
-      || status == svn_wc__db_status_incomplete
-#endif
-      || status == svn_wc__db_status_excluded
-      || status == svn_wc__db_status_server_excluded
-      || status == svn_wc__db_status_not_present)
-    {
-      *props = NULL;
-      return SVN_NO_ERROR;
-    }
+  err = svn_wc__db_read_pristine_props(props, wc_ctx->db, local_abspath,
+                                       result_pool, scratch_pool);
 
-  /* status: normal, moved_here, copied, deleted  */
+  if (err)
+    {
+      if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+        return svn_error_trace(err);
 
-  /* After the above checks, these pristines should always be present.  */
-  return svn_error_trace(
-               svn_wc__db_read_pristine_props(props, db, local_abspath,
-                                              result_pool, scratch_pool));
-}
+      svn_error_clear(err);
 
+      /* Documented behavior is to set *PROPS to NULL */
+      *props = NULL;
+    }
 
-svn_error_t *
-svn_wc_get_pristine_props(apr_hash_t **props,
-                          svn_wc_context_t *wc_ctx,
-                          const char *local_abspath,
-                          apr_pool_t *result_pool,
-                          apr_pool_t *scratch_pool)
-{
-  return svn_error_trace(svn_wc__get_pristine_props(props,
-                                                    wc_ctx->db,
-                                                    local_abspath,
-                                                    result_pool,
-                                                    scratch_pool));
+  return SVN_NO_ERROR;
 }
 
-
 svn_error_t *
 svn_wc_prop_get2(const svn_string_t **value,
                  svn_wc_context_t *wc_ctx,
@@ -1590,6 +1553,7 @@ svn_wc_prop_get2(const svn_string_t **va
                  apr_pool_t *scratch_pool)
 {
   enum svn_prop_kind kind = svn_property_kind2(name);
+  svn_error_t *err;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -1600,8 +1564,18 @@ svn_wc_prop_get2(const svn_string_t **va
                                _("Property '%s' is an entry property"), name);
     }
 
-  SVN_ERR(svn_wc__internal_propget(value, wc_ctx->db, local_abspath, name,
-                                   result_pool, scratch_pool));
+  err = svn_wc__internal_propget(value, wc_ctx->db, local_abspath, name,
+                                 result_pool, scratch_pool);
+
+  if (err)
+    {
+      if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+        return svn_error_trace(err);
+
+      svn_error_clear(err);
+      /* Documented behavior is to set *VALUE to NULL */
+      *value = NULL;
+    }
 
   return SVN_NO_ERROR;
 }
@@ -1616,35 +1590,15 @@ svn_wc__internal_propget(const svn_strin
 {
   apr_hash_t *prophash = NULL;
   enum svn_prop_kind kind = svn_property_kind2(name);
-  svn_boolean_t hidden;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(kind != svn_prop_entry_kind);
 
-  /* This returns SVN_ERR_WC_PATH_NOT_FOUND for unversioned paths for us */
-  SVN_ERR(svn_wc__db_node_hidden(&hidden, db, local_abspath, scratch_pool));
-  if (hidden)
-    {
-      /* The node is not present, or not really "here". Therefore, the
-         property is not present.  */
-      *value = NULL;
-      return SVN_NO_ERROR;
-    }
-
   if (kind == svn_prop_wc_kind)
     {
-      svn_error_t *err;
-      /* If no dav cache can be found, just set VALUE to NULL (for
-         compatibility with pre-WC-NG code). */
-      err = svn_wc__db_base_get_dav_cache(&prophash, db, local_abspath,
-                                          result_pool, scratch_pool);
-      if (err && (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND))
-        {
-          *value = NULL;
-          svn_error_clear(err);
-          return SVN_NO_ERROR;
-        }
-      SVN_ERR_W(err, _("Failed to load properties"));
+      SVN_ERR_W(svn_wc__db_base_get_dav_cache(&prophash, db, local_abspath,
+                                              result_pool, scratch_pool),
+                _("Failed to load properties"));
     }
   else
     {
@@ -1665,47 +1619,38 @@ svn_wc__internal_propget(const svn_strin
 
 /* The special Subversion properties are not valid for all node kinds.
    Return an error if NAME is an invalid Subversion property for PATH which
-   is of kind NODE_KIND. */
+   is of kind NODE_KIND.  NAME must be in the "svn:" name space.
+
+   Note that we only disallow the property if we're sure it's one that
+   already has a meaning for a different node kind.  We don't disallow
+   setting an *unknown* svn: prop here, at this level; a higher level
+   should disallow that if desired.
+  */
 static svn_error_t *
 validate_prop_against_node_kind(const char *name,
                                 const char *path,
                                 svn_node_kind_t node_kind,
                                 apr_pool_t *pool)
 {
-
-  const char *file_prohibit[] = { SVN_PROP_IGNORE,
-                                  SVN_PROP_EXTERNALS,
-                                  SVN_PROP_INHERITABLE_AUTO_PROPS,
-                                  SVN_PROP_INHERITABLE_IGNORES,
-                                  NULL };
-  const char *dir_prohibit[] = { SVN_PROP_EXECUTABLE,
-                                 SVN_PROP_KEYWORDS,
-                                 SVN_PROP_EOL_STYLE,
-                                 SVN_PROP_MIME_TYPE,
-                                 SVN_PROP_NEEDS_LOCK,
-                                 NULL };
-  const char **node_kind_prohibit;
   const char *path_display
     = svn_path_is_url(path) ? path : svn_dirent_local_style(path, pool);
 
   switch (node_kind)
     {
     case svn_node_dir:
-      node_kind_prohibit = dir_prohibit;
-      while (*node_kind_prohibit)
-        if (strcmp(name, *node_kind_prohibit++) == 0)
-          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                                   _("Cannot set '%s' on a directory ('%s')"),
-                                   name, path_display);
+      if (! svn_prop_is_known_svn_dir_prop(name)
+          && svn_prop_is_known_svn_file_prop(name))
+        return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                 _("Cannot set '%s' on a directory ('%s')"),
+                                 name, path_display);
       break;
     case svn_node_file:
-      node_kind_prohibit = file_prohibit;
-      while (*node_kind_prohibit)
-        if (strcmp(name, *node_kind_prohibit++) == 0)
-          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                                   _("Cannot set '%s' on a file ('%s')"),
-                                   name,
-                                   path_display);
+      if (! svn_prop_is_known_svn_file_prop(name)
+          && svn_prop_is_known_svn_dir_prop(name))
+        return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                 _("Cannot set '%s' on a file ('%s')"),
+                                 name,
+                                 path_display);
       break;
     default:
       return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
@@ -1787,17 +1732,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 *
@@ -1952,6 +1894,7 @@ do_propset(svn_wc__db_t *db,
                                                      notify_action,
                                                      scratch_pool);
       notify->prop_name = name;
+      notify->kind = kind;
 
       (*notify_func)(notify_baton, notify, scratch_pool);
     }
@@ -1988,7 +1931,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;
@@ -2012,9 +1955,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)
@@ -2029,38 +1971,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,
@@ -2070,12 +2008,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
     {
@@ -2168,9 +2117,34 @@ svn_wc_canonicalize_svn_prop(const svn_s
              an svn:externals line.  As it happens, our parse code
              checks for this, so all we have to is invoke it --
              we're not interested in the parsed result, only in
-             whether or the parsing errored. */
-          SVN_ERR(svn_wc_parse_externals_description3
-                  (NULL, path, propval->data, FALSE, pool));
+             whether or not the parsing errored. */
+          apr_array_header_t *externals = NULL;
+          apr_array_header_t *duplicate_targets = NULL;
+          SVN_ERR(svn_wc_parse_externals_description3(&externals, path,
+                                                      propval->data, FALSE,
+                                                      /*scratch_*/pool));
+          SVN_ERR(svn_wc__externals_find_target_dups(&duplicate_targets,
+                                                     externals,
+                                                     /*scratch_*/pool,
+                                                     /*scratch_*/pool));
+          if (duplicate_targets && duplicate_targets->nelts > 0)
+            {
+              const char *more_str = "";
+              if (duplicate_targets->nelts > 1)
+                {
+                  more_str = apr_psprintf(/*scratch_*/pool,
+                               _(" (%d more duplicate targets found)"),
+                               duplicate_targets->nelts - 1);
+                }
+              return svn_error_createf(
+                SVN_ERR_WC_DUPLICATE_EXTERNALS_TARGET, NULL,
+                _("Invalid %s property on '%s': "
+                  "target '%s' appears more than once%s"),
+                SVN_PROP_EXTERNALS,
+                svn_dirent_local_style(path, pool),
+                APR_ARRAY_IDX(duplicate_targets, 0, const char*),
+                more_str);
+            }
         }
     }
   else if (strcmp(propname, SVN_PROP_KEYWORDS) == 0)
@@ -2338,132 +2312,6 @@ svn_wc__has_magic_property(const apr_arr
   return FALSE;
 }
 
-/* Remove all prop name value pairs from PROP_HASH where the property
-   name is not PROPNAME. */
-static void
-filter_unwanted_props(apr_hash_t *prop_hash,
-                      const char * propname,
-                      apr_pool_t *scratch_pool)
-{
-  apr_hash_index_t *hi;
-
-  for (hi = apr_hash_first(scratch_pool, prop_hash);
-       hi;
-       hi = apr_hash_next(hi))
-    {
-      const char *ipropname = svn__apr_hash_index_key(hi);
-
-      if (strcmp(ipropname, propname) != 0)
-        apr_hash_set(prop_hash, ipropname, APR_HASH_KEY_STRING, NULL);
-    }
-  return;
-}
-
-svn_error_t *
-svn_wc__internal_get_iprops(apr_array_header_t **inherited_props,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            const char *propname,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool)
-{
-  int i;
-  apr_array_header_t *cached_iprops = NULL;
-  const char *parent_abspath = local_abspath;
-  svn_boolean_t is_wc_root = FALSE;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-
-  SVN_ERR_ASSERT(inherited_props);
-  *inherited_props = apr_array_make(result_pool, 1,
-                                    sizeof(svn_prop_inherited_item_t *));
-
-  /* Walk up to the root of the WC looking for inherited properties.  When we
-     reach the WC root also check for cached inherited properties. */
-  while (TRUE)
-    {
-      apr_hash_t *actual_props;
-      svn_boolean_t is_switched;
-
-      svn_pool_clear(iterpool);
-
-      SVN_ERR(svn_wc__db_is_switched(&is_wc_root, &is_switched, NULL,
-                                     db, parent_abspath, iterpool));
-
-      if (is_switched || is_wc_root)
-        {
-          is_wc_root = TRUE;
-
-          /* If the WC root is also the root of the repository then by
-             definition there are no inheritable properties to be had,
-             but checking for that is just as expensive as fetching them
-             anyway. */
-
-          /* Grab the cached inherited properties for the WC root. */
-          SVN_ERR(svn_wc__db_read_cached_iprops(&cached_iprops, db,
-                                                parent_abspath,
-                                                scratch_pool, iterpool));
-        }
-
-      /* If PARENT_ABSPATH is a true parent of LOCAL_ABSPATH, then
-         LOCAL_ABSPATH can inherit properties from it. */
-      if (strcmp(local_abspath, parent_abspath) != 0)
-        {
-          SVN_ERR(svn_wc__db_read_props(&actual_props, db, parent_abspath,
-                                        result_pool, iterpool));
-          if (actual_props)
-            {
-              /* If we only want PROPNAME filter out any other properties. */
-              if (propname)
-                filter_unwanted_props(actual_props, propname, iterpool);
-
-              if (apr_hash_count(actual_props))
-                {
-                  svn_prop_inherited_item_t *iprop_elt =
-                    apr_pcalloc(result_pool,
-                                sizeof(svn_prop_inherited_item_t));
-                  iprop_elt->path_or_url = apr_pstrdup(result_pool,
-                                                       parent_abspath);
-                  iprop_elt->prop_hash = actual_props;
-                  /* Build the output array in depth-first order. */
-                  svn_sort__array_insert(&iprop_elt, *inherited_props, 0);
-                }
-            }
-        }
-
-      /* Inheritance only goes as far as the nearest WC root. */
-      if (is_wc_root)
-        break;
-
-      /* Keep looking for the WC root. */
-      parent_abspath = svn_dirent_dirname(parent_abspath, scratch_pool);
-    }
-
-  if (cached_iprops)
-    {
-      for (i = cached_iprops->nelts - 1; i >= 0; i--)
-        {
-          svn_prop_inherited_item_t *cached_iprop =
-            APR_ARRAY_IDX(cached_iprops, i, svn_prop_inherited_item_t *);
-
-          /* An empty property hash in the iprops cache means there are no
-             inherited properties. */
-          if (apr_hash_count(cached_iprop->prop_hash) == 0)
-            continue;
-
-          if (propname)
-            filter_unwanted_props(cached_iprop->prop_hash, propname,
-                                  scratch_pool);
-
-          /* If we didn't filter everything then keep this iprop. */
-          if (apr_hash_count(cached_iprop->prop_hash))
-            svn_sort__array_insert(&cached_iprop, *inherited_props, 0);
-        }
-    }
-
-  svn_pool_destroy(iterpool);
-  return SVN_NO_ERROR;
-}
-
 svn_error_t *
 svn_wc__get_iprops(apr_array_header_t **inherited_props,
                    svn_wc_context_t *wc_ctx,
@@ -2472,9 +2320,11 @@ svn_wc__get_iprops(apr_array_header_t **
                    apr_pool_t *result_pool,
                    apr_pool_t *scratch_pool)
 {
-  return svn_error_trace(svn_wc__internal_get_iprops(inherited_props, wc_ctx->db,
-                                               local_abspath, propname,
-                                               result_pool, scratch_pool));
+  return svn_error_trace(
+            svn_wc__db_read_inherited_props(inherited_props,
+                                            wc_ctx->db, local_abspath,
+                                            propname,
+                                            result_pool, scratch_pool));
 }
 
 svn_error_t *

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/props.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/props.h?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/props.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/props.h Tue Dec  4 02:26:18 2012
@@ -127,15 +127,6 @@ svn_wc__props_modified(svn_boolean_t *mo
                        const char *local_abspath,
                        apr_pool_t *scratch_pool);
 
-/* Internal version of svn_wc_get_pristine_props().  */
-svn_error_t *
-svn_wc__get_pristine_props(apr_hash_t **props,
-                           svn_wc__db_t *db,
-                           const char *local_abspath,
-                           apr_pool_t *result_pool,
-                           apr_pool_t *scratch_pool);
-
-
 /* Internal version of svn_wc_prop_list2().  */
 svn_error_t *
 svn_wc__get_actual_props(apr_hash_t **props,

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/status.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/status.c Tue Dec  4 02:26:18 2012
@@ -1028,9 +1028,10 @@ collect_ignore_patterns(apr_array_header
                                      FALSE, result_pool);      
         }
 
-      SVN_ERR(svn_wc__internal_get_iprops(&inherited_props, db, local_abspath,
-                                          SVN_PROP_INHERITABLE_IGNORES,
-                                          scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_read_inherited_props(&inherited_props,
+                                              db, local_abspath,
+                                              SVN_PROP_INHERITABLE_IGNORES,
+                                              scratch_pool, scratch_pool));
       for (i = 0; i < inherited_props->nelts; i++)
         {
           apr_hash_index_t *hi;

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/translate.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/translate.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/translate.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/translate.c Tue Dec  4 02:26:18 2012
@@ -409,8 +409,8 @@ 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__get_pristine_props(&pristine_props, db, local_abspath,
-                                         scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props, db, local_abspath,
+                                             scratch_pool, scratch_pool));
 
       if (pristine_props
             && apr_hash_get(pristine_props,

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/update_editor.c Tue Dec  4 02:26:18 2012
@@ -2394,9 +2394,9 @@ close_directory(void *dir_baton,
   if (db->add_existed)
     {
       /* This node already exists. Grab the current pristine properties. */
-      SVN_ERR(svn_wc__get_pristine_props(&base_props,
-                                         eb->db, db->local_abspath,
-                                         scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_read_pristine_props(&base_props,
+                                             eb->db, db->local_abspath,
+                                             scratch_pool, scratch_pool));
     }
   else if (!db->adding_dir)
     {
@@ -4077,9 +4077,9 @@ close_file(void *file_baton,
   if (fb->add_existed)
     {
       /* This node already exists. Grab the current pristine properties. */
-      SVN_ERR(svn_wc__get_pristine_props(&current_base_props,
-                                         eb->db, fb->local_abspath,
-                                         scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__db_read_pristine_props(&current_base_props,
+                                             eb->db, fb->local_abspath,
+                                             scratch_pool, scratch_pool));
       current_actual_props = local_actual_props;
     }
   else if (!fb->adding_file)

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc-queries.sql Tue Dec  4 02:26:18 2012
@@ -29,7 +29,7 @@
 -- STMT_SELECT_NODE_INFO
 SELECT op_depth, repos_id, repos_path, presence, kind, revision, checksum,
   translated_size, changed_revision, changed_date, changed_author, depth,
-  symlink_target, last_mod_time, properties, moved_here
+  symlink_target, last_mod_time, properties, moved_here, inherited_props
 FROM nodes
 WHERE wc_id = ?1 AND local_relpath = ?2
 ORDER BY op_depth DESC
@@ -38,6 +38,7 @@ ORDER BY op_depth DESC
 SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision,
   checksum, translated_size, changed_revision, changed_date, changed_author,
   depth, symlink_target, last_mod_time, properties, moved_here,
+  inherited_props,
   /* All the columns until now must match those returned by
      STMT_SELECT_NODE_INFO. The implementation of svn_wc__db_read_info()
      assumes that these columns are followed by the lock information) */
@@ -219,6 +220,34 @@ DELETE FROM nodes
 WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
   AND op_depth = 0
 
+-- STMT_DELETE_WORKING_OP_DEPTH
+DELETE FROM nodes
+WHERE wc_id = ?1 
+  AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+  AND op_depth = ?3
+
+-- STMT_SELECT_LOCAL_RELPATH_OP_DEPTH
+SELECT local_relpath
+FROM nodes
+WHERE wc_id = ?1
+  AND (local_relpath = ?2 OR IS_STRICT_DESCENDANT_OF(local_relpath, ?2))
+  AND op_depth = ?3
+
+-- STMT_COPY_NODE_MOVE
+INSERT INTO nodes (
+    wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
+    revision, presence, depth, kind, changed_revision, changed_date,
+    changed_author, checksum, properties, translated_size, last_mod_time,
+    symlink_target, moved_here )
+SELECT
+    wc_id, ?4 /*local_relpath */, ?5 /*op_depth*/, ?6 /* parent_relpath */,
+    repos_id,
+    repos_path, revision, presence, depth, kind, changed_revision,
+    changed_date, changed_author, checksum, properties, translated_size,
+    last_mod_time, symlink_target, 1
+FROM nodes
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3
+
 -- STMT_SELECT_OP_DEPTH_CHILDREN
 SELECT local_relpath FROM nodes
 WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = ?3
@@ -407,10 +436,6 @@ WHERE wc_id = ?1 AND local_relpath = ?2
   AND op_depth = (SELECT MAX(op_depth) FROM nodes
                   WHERE wc_id = ?1 AND local_relpath = ?2)
 
--- STMT_UPDATE_NODE_FILEINFO_OPDEPTH
-UPDATE nodes SET translated_size = ?3, last_mod_time = ?4
-WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?5
-
 -- STMT_INSERT_ACTUAL_CONFLICT
 INSERT INTO actual_node (wc_id, local_relpath, conflict_data, parent_relpath)
 VALUES (?1, ?2, ?3, ?4)
@@ -478,10 +503,6 @@ BEGIN
    WHERE new.changelist IS NOT NULL;
 END
 
--- STMT_INSERT_CHANGELIST_LIST
-INSERT INTO changelist_list(wc_id, local_relpath, notify, changelist)
-VALUES (?1, ?2, ?3, ?4)
-
 -- STMT_FINALIZE_CHANGELIST
 DROP TRIGGER trigger_changelist_list_change;
 DROP TABLE changelist_list;
@@ -798,9 +819,9 @@ INSERT OR REPLACE INTO nodes (
   wc_id, local_relpath, op_depth, parent_relpath, repos_id, repos_path,
   revision, presence, depth, kind, changed_revision, changed_date,
   changed_author, checksum, properties, dav_cache, symlink_target,
-  file_external )
+  inherited_props, file_external )
 VALUES (?1, ?2, 0,
-        ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16,
+        ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17,
         (SELECT file_external FROM nodes
           WHERE wc_id = ?1
             AND local_relpath = ?2
@@ -1444,22 +1465,29 @@ SET inherited_props = ?3
 WHERE (wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0)
 
 /* Select a single path if its base node has cached inherited properties. */
--- STMT_SELECT_INODES
-SELECT local_relpath FROM nodes
+-- STMT_SELECT_IPROPS_NODE
+SELECT local_relpath, repos_path FROM nodes
 WHERE wc_id = ?1
   AND local_relpath = ?2
   AND op_depth = 0
   AND (inherited_props not null)
 
-/* Select all paths whose base nodes at or below a given path, which
+/* Select all paths whose base nodes are below a given path, which
    have cached inherited properties. */
--- STMT_SELECT_INODES_RECURSIVE
-SELECT local_relpath FROM nodes
+-- STMT_SELECT_IPROPS_RECURSIVE
+SELECT local_relpath, repos_path FROM nodes
 WHERE wc_id = ?1
   AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2)
   AND op_depth = 0
   AND (inherited_props not null)
 
+-- STMT_SELECT_IPROPS_CHILDREN
+SELECT local_relpath, repos_path FROM nodes
+WHERE wc_id = ?1
+  AND parent_relpath = ?2
+  AND op_depth = 0
+  AND (inherited_props not null)
+
 /* ------------------------------------------------------------------------- */
 
 /* Grab all the statements related to the schema.  */

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc.h?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc.h Tue Dec  4 02:26:18 2012
@@ -607,15 +607,6 @@ svn_wc__internal_get_repos_relpath(const
                                    apr_pool_t *result_pool,
                                    apr_pool_t *scratch_pool);
 
-/* Internal version of svn_wc__get_iprops() */
-svn_error_t *
-svn_wc__internal_get_iprops(apr_array_header_t **inherited_props,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            const char *propname,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool);
-
 /* Upgrade the wc sqlite database given in SDB for the wc located at
    WCROOT_ABSPATH. It's current/starting format is given by START_FORMAT.
    After the upgrade is complete (to as far as the automatic upgrade will
@@ -764,6 +755,16 @@ svn_wc__fetch_base_func(const char **fil
                         apr_pool_t *result_pool,
                         apr_pool_t *scratch_pool);
 
+/* Find duplicate targets in *EXTERNALS, a list of svn_wc_external_item2_t*
+ * elements, and store each target string in *DUPLICATE_TARGETS as const
+ * char * elements. *DUPLICATE_TARGETS will be NULL if no duplicates were
+ * found. */
+svn_error_t *
+svn_wc__externals_find_target_dups(apr_array_header_t **duplicate_targets,
+                                   apr_array_header_t *externals,
+                                   apr_pool_t *pool,
+                                   apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.c Tue Dec  4 02:26:18 2012
@@ -32,6 +32,7 @@
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
 #include "svn_hash.h"
+#include "svn_sorts.h"
 #include "svn_wc.h"
 #include "svn_checksum.h"
 #include "svn_pools.h"
@@ -320,6 +321,7 @@ static svn_error_t *
 db_read_pristine_props(apr_hash_t **props,
                        svn_wc__db_wcroot_t *wcroot,
                        const char *local_relpath,
+                       svn_boolean_t deleted_ok,
                        apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool);
 
@@ -381,7 +383,18 @@ wclock_owns_lock(svn_boolean_t *own_lock
                  svn_boolean_t exact,
                  apr_pool_t *scratch_pool);
 
+/* Baton for db_is_switched */
+struct db_is_switched_baton_t
+{
+  svn_boolean_t *is_switched;
+  svn_kind_t *kind;
+};
 
+static svn_error_t *
+db_is_switched(void *baton,
+               svn_wc__db_wcroot_t *wcroot,
+               const char *local_relpath,
+               apr_pool_t *scratch_pool);
  
 /* Return the absolute path, in local path style, of LOCAL_RELPATH
    in WCROOT.  */
@@ -3640,7 +3653,7 @@ cross_db_copy(svn_wc__db_wcroot_t *src_w
                     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                     src_wcroot, src_relpath, scratch_pool, scratch_pool));
 
-  SVN_ERR(db_read_pristine_props(&props, src_wcroot, src_relpath,
+  SVN_ERR(db_read_pristine_props(&props, src_wcroot, src_relpath, FALSE,
                                  scratch_pool, scratch_pool));
 
   blank_iwb(&iwb);
@@ -5089,7 +5102,7 @@ set_props_txn(void *baton,
   /* Check if the props are modified. If no changes, then wipe out the
      ACTUAL props.  PRISTINE_PROPS==NULL means that any
      ACTUAL props are okay as provided, so go ahead and set them.  */
-  SVN_ERR(db_read_pristine_props(&pristine_props, wcroot, local_relpath,
+  SVN_ERR(db_read_pristine_props(&pristine_props, wcroot, local_relpath, FALSE,
                                  scratch_pool, scratch_pool));
   if (spb->props && pristine_props)
     {
@@ -7667,7 +7680,7 @@ read_info(svn_wc__db_status_t *status,
           if (op_depth != 0)
             *lock = NULL;
           else
-            *lock = lock_from_columns(stmt_info, 16, 17, 18, 19, result_pool);
+            *lock = lock_from_columns(stmt_info, 17, 18, 19, 20, result_pool);
         }
 
       if (have_work)
@@ -8829,7 +8842,7 @@ db_read_props(void *baton,
     return SVN_NO_ERROR;
 
   /* No local changes. Return the pristine props for this node.  */
-  SVN_ERR(db_read_pristine_props(&rpb->props, wcroot, local_relpath,
+  SVN_ERR(db_read_pristine_props(&rpb->props, wcroot, local_relpath, FALSE,
                                  rpb->result_pool, scratch_pool));
   if (rpb->props == NULL)
     {
@@ -8877,6 +8890,7 @@ static svn_error_t *
 db_read_pristine_props(apr_hash_t **props,
                        svn_wc__db_wcroot_t *wcroot,
                        const char *local_relpath,
+                       svn_boolean_t deleted_ok,
                        apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool)
 {
@@ -8904,9 +8918,8 @@ db_read_pristine_props(apr_hash_t **prop
   presence = svn_sqlite__column_token(stmt, 1, presence_map);
 
   /* For "base-deleted", it is obvious the pristine props are located
-     in the BASE table. Fall through to fetch them.
-     ### BH: Is this really the behavior we want here? */
-  if (presence == svn_wc__db_status_base_deleted)
+     below the current node. Fetch the NODE from the next record. */
+  if (presence == svn_wc__db_status_base_deleted && deleted_ok)
     {
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
@@ -8932,8 +8945,13 @@ db_read_pristine_props(apr_hash_t **prop
       return SVN_NO_ERROR;
     }
 
-  *props = NULL;
-  return svn_error_trace(svn_sqlite__reset(stmt));
+  return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS,
+                           svn_sqlite__reset(stmt),
+                           _("The node '%s' has a status that"
+                             " has no properties."),
+                           path_for_error_message(wcroot,
+                                                  local_relpath,
+                                                  scratch_pool));
 }
 
 
@@ -8953,7 +8971,7 @@ svn_wc__db_read_pristine_props(apr_hash_
                               local_abspath, scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
 
-  SVN_ERR(db_read_pristine_props(props, wcroot, local_relpath,
+  SVN_ERR(db_read_pristine_props(props, wcroot, local_relpath, TRUE,
                                  result_pool, scratch_pool));
   return SVN_NO_ERROR;
 }
@@ -9018,6 +9036,45 @@ svn_wc__db_prop_retrieve_recursive(apr_h
   return svn_error_trace(svn_sqlite__reset(stmt));
 }
 
+/* Baton for db_read_cached_iprops */
+struct read_cached_iprops_baton_t
+{
+  apr_array_header_t *iprops;
+  apr_pool_t *result_pool;
+};
+
+/* Implements svn_wc__db_txn_callback_t for svn_wc__db_read_cached_iprops */
+static svn_error_t *
+db_read_cached_iprops(void *baton,
+                      svn_wc__db_wcroot_t *wcroot,
+                      const char *local_relpath,
+                      apr_pool_t *scratch_pool)
+{
+  struct read_cached_iprops_baton_t *rib = baton;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_IPROPS));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (!have_row)
+    {
+      return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND,
+                               svn_sqlite__reset(stmt),
+                               _("The node '%s' was not found."),
+                               path_for_error_message(wcroot, local_relpath,
+                                                      scratch_pool));
+    }
+
+  SVN_ERR(svn_sqlite__column_iprops(&rib->iprops, stmt, 0,
+                                    rib->result_pool, scratch_pool));
+
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__db_read_cached_iprops(apr_array_header_t **iprops,
                               svn_wc__db_t *db,
@@ -9027,8 +9084,7 @@ svn_wc__db_read_cached_iprops(apr_array_
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
+  struct read_cached_iprops_baton_t rcib;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
@@ -9036,61 +9092,261 @@ svn_wc__db_read_cached_iprops(apr_array_
                                                 db, local_abspath,
                                                 scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
-  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_IPROPS));
-  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
-  SVN_ERR(svn_sqlite__step(&have_row, stmt));
 
-  if (!have_row)
+  rcib.result_pool = result_pool;
+
+  /* Don't use with_txn yet, as we perform just a single transaction */
+  SVN_ERR(db_read_cached_iprops(&rcib, wcroot, local_relpath, scratch_pool));
+
+  if (rcib.iprops)
+    *iprops = rcib.iprops;
+  else
     {
-      /* No cached iprops. */
-      *iprops = NULL;
+      *iprops = apr_array_make(result_pool, 0,
+                               sizeof(svn_prop_inherited_item_t *));
     }
-  else
+
+  return SVN_NO_ERROR;
+}
+
+/* Remove all prop name value pairs from PROP_HASH where the property
+   name is not PROPNAME. */
+static void
+filter_unwanted_props(apr_hash_t *prop_hash,
+                      const char * propname,
+                      apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(scratch_pool, prop_hash);
+       hi;
+       hi = apr_hash_next(hi))
     {
-      SVN_ERR(svn_sqlite__column_iprops(iprops, stmt, 0, result_pool,
-                                        scratch_pool));
-      if (!*iprops)
-        *iprops = apr_array_make(result_pool, 0,
-                                 sizeof(svn_prop_inherited_item_t *));
+      const char *ipropname = svn__apr_hash_index_key(hi);
 
-     }
+      if (strcmp(ipropname, propname) != 0)
+        apr_hash_set(prop_hash, ipropname, APR_HASH_KEY_STRING, NULL);
+    }
+  return;
+}
 
-  SVN_ERR(svn_sqlite__reset(stmt));
+/* Baton for db_read_inherited_props */
+struct read_inherited_props_baton_t
+{
+  apr_array_header_t *iprops;
+  const char *propname;
+  apr_pool_t *result_pool;
+};
+
+/* Implements svn_wc__db_txn_callback_t for svn_wc__db_read_inherited_props */
+static svn_error_t *
+db_read_inherited_props(void *baton,
+                        svn_wc__db_wcroot_t *wcroot,
+                        const char *local_relpath,
+                        apr_pool_t *scratch_pool)
+{
+  struct read_inherited_props_baton_t *ripb = baton;
+  int i;
+  apr_array_header_t *cached_iprops = NULL;
+  const char *parent_relpath = local_relpath;
+  svn_boolean_t is_wc_root = FALSE;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_pool_t *result_pool = ripb->result_pool;
+
+  ripb->iprops = apr_array_make(ripb->result_pool, 1,
+                                sizeof(svn_prop_inherited_item_t *));
+
+  /* Walk up to the root of the WC looking for inherited properties.  When we
+     reach the WC root also check for cached inherited properties. */
+  while (TRUE)
+    {
+      apr_hash_t *actual_props;
+      svn_boolean_t is_switched;
+      struct db_is_switched_baton_t swb;
+
+      svn_pool_clear(iterpool);
+
+      swb.is_switched = &is_switched;
+      swb.kind = NULL;
+
+      if (*parent_relpath == '\0')
+        {
+          is_switched = FALSE;
+          is_wc_root = TRUE;
+        }
+      else
+        SVN_ERR(db_is_switched(&swb, wcroot, parent_relpath, scratch_pool));
+
+      if (is_switched || is_wc_root)
+        {
+          struct read_cached_iprops_baton_t rib;
+          is_wc_root = TRUE;
+
+          rib.result_pool = scratch_pool;
+
+          /* If the WC root is also the root of the repository then by
+             definition there are no inheritable properties to be had,
+             but checking for that is just as expensive as fetching them
+             anyway. */
+
+          /* Grab the cached inherited properties for the WC root. */
+          SVN_ERR(db_read_cached_iprops(&rib, wcroot, parent_relpath,
+                                       iterpool));
+
+          cached_iprops = rib.iprops;
+        }
+
+      /* If PARENT_ABSPATH is a true parent of LOCAL_ABSPATH, then
+         LOCAL_ABSPATH can inherit properties from it. */
+      if (strcmp(local_relpath, parent_relpath) != 0)
+        {
+          struct db_read_props_baton_t rpb;
+          rpb.result_pool = result_pool;
+
+          SVN_ERR(db_read_props(&rpb, wcroot, parent_relpath, iterpool));
+
+          actual_props = rpb.props;
+
+          if (actual_props)
+            {
+              /* If we only want PROPNAME filter out any other properties. */
+              if (ripb->propname)
+                filter_unwanted_props(actual_props, ripb->propname, iterpool);
+
+              if (apr_hash_count(actual_props))
+                {
+                  svn_prop_inherited_item_t *iprop_elt =
+                    apr_pcalloc(ripb->result_pool,
+                                sizeof(svn_prop_inherited_item_t));
+                  iprop_elt->path_or_url = svn_dirent_join(wcroot->abspath,
+                                                           parent_relpath,
+                                                           result_pool);
+
+                  iprop_elt->prop_hash = actual_props;
+                  /* Build the output array in depth-first order. */
+                  svn_sort__array_insert(&iprop_elt, ripb->iprops, 0);
+                }
+            }
+        }
+
+      /* Inheritance only goes as far as the nearest WC root. */
+      if (is_wc_root)
+        break;
+
+      /* Keep looking for the WC root. */
+      parent_relpath = svn_relpath_dirname(parent_relpath, scratch_pool);
+    }
+
+  if (cached_iprops)
+    {
+      for (i = cached_iprops->nelts - 1; i >= 0; i--)
+        {
+          svn_prop_inherited_item_t *cached_iprop =
+            APR_ARRAY_IDX(cached_iprops, i, svn_prop_inherited_item_t *);
+
+          /* An empty property hash in the iprops cache means there are no
+             inherited properties. */
+          if (apr_hash_count(cached_iprop->prop_hash) == 0)
+            continue;
 
+          if (ripb->propname)
+            filter_unwanted_props(cached_iprop->prop_hash, ripb->propname,
+                                  scratch_pool);
+
+          /* If we didn't filter everything then keep this iprop. */
+          if (apr_hash_count(cached_iprop->prop_hash))
+            svn_sort__array_insert(&cached_iprop, ripb->iprops, 0);
+        }
+    }
+
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
-/* Recursive body of svn_wc__db_get_children_with_cached_iprops. */
-static svn_error_t *
-get_children_with_cached_iprops(apr_hash_t *iprop_paths,
-                                svn_depth_t depth,
-                                const char *local_abspath,
+svn_error_t *
+svn_wc__db_read_inherited_props(apr_array_header_t **iprops,
                                 svn_wc__db_t *db,
+                                const char *local_abspath,
+                                const char *propname,
                                 apr_pool_t *result_pool,
                                 apr_pool_t *scratch_pool)
 {
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
-  svn_sqlite__stmt_t *stmt;
-  svn_boolean_t have_row;
+  struct read_inherited_props_baton_t ripb;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
-                                                local_abspath, scratch_pool,
-                                                scratch_pool));
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+                                                db, local_abspath,
+                                                scratch_pool, scratch_pool));
   VERIFY_USABLE_WCROOT(wcroot);
-  if (depth == svn_depth_empty
-      || depth == svn_depth_files
-      || depth == svn_depth_immediates)
+
+  ripb.iprops = NULL;
+  ripb.propname = propname;
+  ripb.result_pool = result_pool;
+
+  SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_read_inherited_props,
+                              &ripb, scratch_pool));
+
+  *iprops = ripb.iprops;
+  return SVN_NO_ERROR;
+}
+
+/* Baton for get_children_with_cached_iprops */
+struct get_children_with_cached_baton_t
+{
+  svn_depth_t depth;
+  apr_hash_t *iprop_paths;
+  apr_pool_t *result_pool;
+};
+
+/* Implements svn_wc__db_txn_callback_t for
+   svn_wc__db_get_children_with_cached_iprops. */
+static svn_error_t *
+get_children_with_cached_iprops(void *baton,
+                                svn_wc__db_wcroot_t *wcroot,
+                                const char *local_relpath,
+                                apr_pool_t *scratch_pool)
+{
+  struct get_children_with_cached_baton_t *cwcb = baton;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  apr_hash_t *iprop_paths = cwcb->iprop_paths;
+  apr_pool_t *result_pool = cwcb->result_pool;
+
+  /* First check if LOCAL_RELPATH itself has iprops */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_IPROPS_NODE));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  if (have_row)
+   {
+      const char *relpath_with_cache = svn_sqlite__column_text(stmt, 0,
+                                                               NULL);
+      const char *abspath_with_cache = svn_dirent_join(wcroot->abspath,
+                                                       relpath_with_cache,
+                                                       result_pool);
+      apr_hash_set(iprop_paths, abspath_with_cache, APR_HASH_KEY_STRING,
+                   svn_sqlite__column_text(stmt, 1, result_pool));
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  if (cwcb->depth == svn_depth_empty)
+    return SVN_NO_ERROR;
+
+  /* Now fetch information for children or all descendants */
+  if (cwcb->depth == svn_depth_files
+      || cwcb->depth == svn_depth_immediates)
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_SELECT_INODES));  
+                                        STMT_SELECT_IPROPS_CHILDREN));
     }
   else /* Default to svn_depth_infinity. */
     {
       SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
-                                        STMT_SELECT_INODES_RECURSIVE));
+                                        STMT_SELECT_IPROPS_RECURSIVE));
     }
 
   SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
@@ -9104,46 +9360,50 @@ get_children_with_cached_iprops(apr_hash
                                                        relpath_with_cache,
                                                        result_pool);
       apr_hash_set(iprop_paths, abspath_with_cache, APR_HASH_KEY_STRING,
-                   abspath_with_cache);
+                   svn_sqlite__column_text(stmt, 1, result_pool));
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
     }
 
   SVN_ERR(svn_sqlite__reset(stmt));
 
-  if (depth == svn_depth_files || depth == svn_depth_immediates)
+  /* For depth files we should filter non files */
+  if (cwcb->depth == svn_depth_files)
     {
-      const apr_array_header_t *rel_children;
-      int i;
+      apr_hash_index_t *hi;
       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
-      SVN_ERR(svn_wc__db_read_children_of_working_node(&rel_children,
-                                                       db, local_abspath,
-                                                       scratch_pool,
-                                                       scratch_pool));
-      for (i = 0; i < rel_children->nelts; i++)
+      for (hi = apr_hash_first(scratch_pool, iprop_paths);
+           hi;
+           hi = apr_hash_next(hi))
         {
-          const char *child_abspath;
+          const char *child_abspath = svn__apr_hash_index_key(hi);
+          const char *child_relpath;
+          svn_kind_t child_kind;
 
           svn_pool_clear(iterpool);
-          child_abspath = svn_dirent_join(
-            local_abspath, APR_ARRAY_IDX(rel_children, i, const char *),
-            iterpool);
 
-          if (depth == svn_depth_files)
-            {
-              svn_kind_t child_kind;
+          child_relpath = svn_dirent_is_child(local_relpath, child_abspath,
+                                              NULL);
 
-              SVN_ERR(svn_wc__db_read_kind(&child_kind, db, child_abspath,
-                                           FALSE, FALSE, iterpool));
-              if (child_kind != svn_kind_file)
-                continue;
+          if (! child_relpath)
+            {
+              continue; /* local_relpath itself */
             }
 
-          SVN_ERR(get_children_with_cached_iprops(iprop_paths,
-                                                  svn_depth_empty,
-                                                  child_abspath, db,
-                                                  result_pool,
-                                                  iterpool));
+          SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &child_kind, NULL,
+                                                    NULL, NULL, NULL, NULL,
+                                                    NULL, NULL, NULL, NULL,
+                                                    NULL, NULL, NULL,
+                                                    wcroot, child_relpath,
+                                                    scratch_pool,
+                                                    scratch_pool));
+
+          /* Filter if not a file */
+          if (child_kind != svn_kind_file)
+            {
+              apr_hash_set(iprop_paths, child_abspath, APR_HASH_KEY_STRING,
+                           NULL);
+            }
         }
 
       svn_pool_destroy(iterpool);
@@ -9160,10 +9420,26 @@ svn_wc__db_get_children_with_cached_ipro
                                            apr_pool_t *result_pool,
                                            apr_pool_t *scratch_pool)
 {
-  *iprop_paths = apr_hash_make(result_pool);
-  SVN_ERR(get_children_with_cached_iprops(*iprop_paths, depth,
-                                          local_abspath, db, result_pool,
-                                          scratch_pool));
+  svn_wc__db_wcroot_t *wcroot;
+  const char *local_relpath;
+  struct get_children_with_cached_baton_t cwcb;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+                                                local_abspath, scratch_pool,
+                                                scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  cwcb.iprop_paths = apr_hash_make(result_pool);
+  cwcb.depth = depth;
+  cwcb.result_pool = result_pool;
+
+  SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath,
+                              get_children_with_cached_iprops, &cwcb,
+                              scratch_pool));
+
+  *iprop_paths = cwcb.iprop_paths;
   return SVN_NO_ERROR;
 }
 
@@ -9669,6 +9945,7 @@ commit_node(void *baton,
   svn_sqlite__stmt_t *stmt_act;
   svn_boolean_t have_act;
   svn_string_t prop_blob = { 0 };
+  svn_string_t inherited_prop_blob = { 0 };
   const char *changelist = NULL;
   const char *parent_relpath;
   svn_wc__db_status_t new_presence;
@@ -9738,6 +10015,10 @@ commit_node(void *baton,
     prop_blob.data = svn_sqlite__column_blob(stmt_info, 14, &prop_blob.len,
                                              scratch_pool);
 
+  inherited_prop_blob.data = svn_sqlite__column_blob(stmt_info, 16,
+                                                     &inherited_prop_blob.len,
+                                                     scratch_pool);
+
   if (cb->keep_changelist && have_act)
     changelist = svn_sqlite__column_text(stmt_act, 0, scratch_pool);
 
@@ -9824,6 +10105,11 @@ commit_node(void *baton,
                                     scratch_pool));
   SVN_ERR(svn_sqlite__bind_properties(stmt, 15, cb->new_dav_cache,
                                       scratch_pool));
+  if (inherited_prop_blob.data != NULL)
+    {
+      SVN_ERR(svn_sqlite__bind_blob(stmt, 17, inherited_prop_blob.data,
+                                    inherited_prop_blob.len));
+    }
 
   SVN_ERR(svn_sqlite__step_done(stmt));
 
@@ -12458,13 +12744,6 @@ svn_wc__db_is_wcroot(svn_boolean_t *is_r
    return SVN_NO_ERROR;
 }
 
-/* Baton for db_is_switched */
-struct db_is_switched_baton_t
-{
-  svn_boolean_t *is_switched;
-  svn_kind_t *kind;
-};
-
 /* This implements svn_wc__db_txn_callback_t for svn_wc_db__is_switched */
 static svn_error_t *
 db_is_switched(void *baton,

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db.h Tue Dec  4 02:26:18 2012
@@ -2094,6 +2094,26 @@ svn_wc__db_read_pristine_props(apr_hash_
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 
+
+/**
+ * Set @a *inherited_props to a depth-first ordered array of
+ * #svn_prop_inherited_item_t * structures representing the properties
+ * inherited by @a local_abspath from the ACTUAL tree above
+ * @a local_abspath (looking through to the WORKING or BASE tree as
+ * required), up to and including the root of the working copy and
+ * any cached inherited properties inherited by the root.
+ *
+ * Allocate @a *inherited_props in @a result_pool.  Use @a scratch_pool
+ * for temporary allocations.
+ */
+svn_error_t *
+svn_wc__db_read_inherited_props(apr_array_header_t **iprops,
+                                svn_wc__db_t *db,
+                                const char *local_abspath,
+                                const char *propname,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool);
+
 /* Read a BASE node's inherited property information.
 
    Set *IPROPS to to a depth-first ordered array of
@@ -2116,9 +2136,11 @@ svn_wc__db_read_cached_iprops(apr_array_
 /* Find BASE nodes with cached inherited properties.
 
    Set *IPROPS_PATHS to a hash mapping const char * absolute working copy
-   paths to the same for each path in the working copy at or below
-   LOCAL_ABSPATH, limited by DEPTH, that has cached inherited properties
-   for the BASE node of the path.  Allocate *IPROP_PATHS in RESULT_POOL.
+   paths to the repos_relpath of the path for each path in the working copy
+   at or below LOCAL_ABSPATH, limited by DEPTH, that has cached inherited
+   properties for the BASE node of the path.
+
+   Allocate *IPROP_PATHS in RESULT_POOL.
    Use SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_wc__db_get_children_with_cached_iprops(apr_hash_t **iprop_paths,
@@ -3225,8 +3247,8 @@ svn_wc__db_follow_moved_to(apr_array_hea
  * need to run as part of marking the conflict resolved. */
 svn_error_t *
 svn_wc__db_update_moved_away_conflict_victim(svn_skel_t **work_items,
-                                             const char *victim_abspath,
                                              svn_wc__db_t *db,
+                                             const char *victim_abspath,
                                              svn_wc_notify_func2_t notify_func,
                                              void *notify_baton,
                                              svn_cancel_func_t cancel_func,

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/wc_db_update_move.c Tue Dec  4 02:26:18 2012
@@ -53,14 +53,17 @@
 
 /*
  * Receiver code.
+ *
+ * The receiver is an editor that, when driven with a certain change, will
+ * merge the edits into the 'actual' layer of a moved subtree.
  */
 
 struct tc_editor_baton {
-  const char *move_root_src_relpath;
-  const char *move_root_dst_relpath;
+  svn_skel_t **work_items;
   svn_wc__db_t *db;
   svn_wc__db_wcroot_t *wcroot;
-  svn_skel_t **work_items;
+  const char *move_root_src_relpath;
+  const char *move_root_dst_relpath;
   svn_wc_conflict_version_t *old_version;
   svn_wc_conflict_version_t *new_version;
   svn_wc_notify_func2_t notify_func;
@@ -410,6 +413,13 @@ tc_editor_abort(void *baton,
   return SVN_NO_ERROR;
 }
 
+/* An editor.
+ *
+ * This editor will merge the edits into the 'actual' tree at
+ * MOVE_ROOT_DST_RELPATH (in struct tc_editor_baton),
+ * perhaps raising conflicts if necessary.
+ *
+ */
 static const svn_editor_cb_many_t editor_ops = {
   tc_editor_add_directory,
   tc_editor_add_file,
@@ -429,6 +439,18 @@ static const svn_editor_cb_many_t editor
 
 /*
  * Driver code.
+ *
+ * The scenario is that a subtree has been locally moved, and then the base
+ * layer on the source side of the move has received an update to a new
+ * state.  The destination subtree has not yet been updated, and still
+ * matches the pre-update state of the source subtree.
+ *
+ * The edit driver drives the receiver with the difference between the
+ * pre-update state (as found now at the move-destination) and the
+ * post-update state (found now at the move-source).
+ *
+ * We currently assume that both the pre-update and post-update states are
+ * single-revision.
  */
 
 /* Set *OPERATION, *LOCAL_CHANGE, *INCOMING_CHANGE, *OLD_VERSION, *NEW_VERSION
@@ -442,8 +464,8 @@ get_tc_info(svn_wc_operation_t *operatio
             svn_wc_conflict_action_t *incoming_change,
             svn_wc_conflict_version_t **old_version,
             svn_wc_conflict_version_t **new_version,
-            const char *src_abspath,
             svn_wc__db_t *db,
+            const char *src_abspath,
             apr_pool_t *result_pool,
             apr_pool_t *scratch_pool)
 {
@@ -650,7 +672,93 @@ update_moved_away_subtree(svn_editor_t *
   return SVN_NO_ERROR;
 }
 
-/* ### Drive TC_EDITOR so as to ...
+/* Update the single op-depth layer in the move destination subtree
+   rooted at DST_RELPATH to make it match the move source subtree
+   rooted at SRC_RELPATH. */
+static svn_error_t *
+replace_moved_layer(const char *src_relpath,
+                    const char *dst_relpath,
+                    svn_wc__db_t *db,
+                    svn_wc__db_wcroot_t *wcroot,
+                    apr_pool_t *scratch_pool)
+{
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+  int src_op_depth;
+  int dst_op_depth = relpath_depth(dst_relpath);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_NODE_INFO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, src_relpath));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  if (have_row)
+    src_op_depth = svn_sqlite__column_int(stmt, 0);
+  SVN_ERR(svn_sqlite__reset(stmt));
+  if (!have_row)
+    return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
+                             _("'%s' is not deleted"),
+                             svn_dirent_local_style(src_relpath,
+                                                    scratch_pool));
+
+  /* Delete entire subtree at one op-depth. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_DELETE_WORKING_OP_DEPTH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                            dst_relpath, dst_op_depth));
+  SVN_ERR(svn_sqlite__step_done(stmt));
+
+  /* Copy entire subtree at one op-depth. */
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+                                    STMT_SELECT_LOCAL_RELPATH_OP_DEPTH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id,
+                            src_relpath, src_op_depth));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  while (have_row)
+    {
+      svn_error_t *err;
+      svn_sqlite__stmt_t *stmt2;
+      const char *src_cp_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *dst_cp_relpath
+        = svn_relpath_join(dst_relpath,
+                           svn_relpath_skip_ancestor(src_relpath,
+                                                     src_cp_relpath),
+                           scratch_pool);
+
+      err = svn_sqlite__get_statement(&stmt2, wcroot->sdb,
+                                      STMT_COPY_NODE_MOVE);
+      if (!err)
+        err = svn_sqlite__bindf(stmt2, "isdsds", wcroot->wc_id,
+                                src_cp_relpath, src_op_depth,
+                                dst_cp_relpath, dst_op_depth,
+                                svn_relpath_dirname(dst_cp_relpath,
+                                                    scratch_pool));
+      if (!err)
+        err = svn_sqlite__step_done(stmt2);
+      if (err)
+        return svn_error_compose_create(err, svn_sqlite__reset(stmt));
+ 
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+
+  /* TODO: extend/retract any base-deleted layers to account for
+     added/removed nodes in the replaced layer. */
+
+  return SVN_NO_ERROR;
+}
+
+/* Transfer changes from the move source to the move destination.
+ *
+ * Drive the editor TC_EDITOR with the difference between DST_RELPATH
+ * (at its own op-depth) and SRC_RELPATH (at op-depth zero).
+ *
+ * Then update the single op-depth layer in the move destination subtree
+ * rooted at DST_RELPATH to make it match the move source subtree
+ * rooted at SRC_RELPATH.
+ *
+ * ### And the other params?
  */
 static svn_error_t *
 drive_tree_conflict_editor(svn_editor_t *tc_editor,
@@ -680,17 +788,9 @@ drive_tree_conflict_editor(svn_editor_t 
                                               src_relpath, scratch_pool),
                               scratch_pool));
 
-  /*
-   * Drive the TC editor to transfer incoming changes from the move source
-   * to the move destination.
-   *
-   * The pre-update tree is within dst at the op-depth of the move's op-root.
-   * The post-update base tree is within src at op-depth zero.
-   *
-   * We walk the move source (i.e. the post-update tree), comparing each node
+  /* We walk the move source (i.e. the post-update tree), comparing each node
    * with the equivalent node at the move destination and applying the update
-   * to nodes at the move destination.
-   */
+   * to nodes at the move destination. */
   if (old_version->node_kind == svn_node_file)
     SVN_ERR(update_moved_away_file(tc_editor, src_relpath, dst_relpath,
                                    dst_relpath, old_version->peg_rev,
@@ -702,18 +802,20 @@ drive_tree_conflict_editor(svn_editor_t 
 
   SVN_ERR(svn_editor_complete(tc_editor));
 
+  SVN_ERR(replace_moved_layer(src_relpath, dst_relpath, db, wcroot,
+                              scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
 struct update_moved_away_conflict_victim_baton {
   svn_skel_t **work_items;
-  const char *victim_relpath;
+  svn_wc__db_t *db;
   svn_wc_operation_t operation;
   svn_wc_conflict_reason_t local_change;
   svn_wc_conflict_action_t incoming_change;
   svn_wc_conflict_version_t *old_version;
   svn_wc_conflict_version_t *new_version;
-  svn_wc__db_t *db;
   svn_wc_notify_func2_t notify_func;
   void *notify_baton;
   svn_cancel_func_t cancel_func;
@@ -737,16 +839,15 @@ update_moved_away_conflict_victim(void *
 
   /* Construct editor baton. */
   tc_editor_baton = apr_pcalloc(scratch_pool, sizeof(*tc_editor_baton));
-  tc_editor_baton->move_root_src_relpath = b->victim_relpath;
+  tc_editor_baton->move_root_src_relpath = victim_relpath;
   SVN_ERR(svn_wc__db_scan_deletion_internal(
             NULL, &tc_editor_baton->move_root_dst_relpath, NULL, NULL,
-            wcroot, b->victim_relpath, scratch_pool, scratch_pool));
+            wcroot, victim_relpath, scratch_pool, scratch_pool));
   if (tc_editor_baton->move_root_dst_relpath == NULL)
     return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
                              _("The node '%s' has not been moved away"),
                              svn_dirent_local_style(
-                               svn_dirent_join(wcroot->abspath,
-                                               b->victim_relpath,
+                               svn_dirent_join(wcroot->abspath, victim_relpath,
                                                scratch_pool),
                                scratch_pool));
   tc_editor_baton->old_version= b->old_version;
@@ -782,8 +883,8 @@ update_moved_away_conflict_victim(void *
 
 svn_error_t *
 svn_wc__db_update_moved_away_conflict_victim(svn_skel_t **work_items,
-                                             const char *victim_abspath,
                                              svn_wc__db_t *db,
+                                             const char *victim_abspath,
                                              svn_wc_notify_func2_t notify_func,
                                              void *notify_baton,
                                              svn_cancel_func_t cancel_func,
@@ -794,15 +895,11 @@ svn_wc__db_update_moved_away_conflict_vi
   struct update_moved_away_conflict_victim_baton b;
   svn_wc__db_wcroot_t *wcroot;
   const char *local_relpath;
-  svn_wc_operation_t operation;
-  svn_wc_conflict_reason_t local_change;
-  svn_wc_conflict_action_t incoming_change;
-  svn_wc_conflict_version_t *old_version;
-  svn_wc_conflict_version_t *new_version;
 
-  SVN_ERR(get_tc_info(&operation, &local_change, &incoming_change,
-                      &old_version, &new_version,
-                      victim_abspath, db, scratch_pool, scratch_pool));
+  SVN_ERR(get_tc_info(&b.operation, &b.local_change, &b.incoming_change,
+                      &b.old_version, &b.new_version,
+                      db, victim_abspath,
+                      scratch_pool, scratch_pool));
 
   SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
                                                 db, victim_abspath,
@@ -810,12 +907,6 @@ svn_wc__db_update_moved_away_conflict_vi
   VERIFY_USABLE_WCROOT(wcroot);
 
   b.work_items = work_items;
-  b.victim_relpath = local_relpath;
-  b.operation = operation;
-  b.local_change = local_change;
-  b.incoming_change = incoming_change;
-  b.old_version = old_version;
-  b.new_version = new_version;
   b.db = db;
   b.notify_func = notify_func;
   b.notify_baton = notify_baton;

Modified: subversion/branches/ev2-export/subversion/mod_dav_svn/reports/inherited-props.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/mod_dav_svn/reports/inherited-props.c?rev=1416748&r1=1416747&r2=1416748&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/mod_dav_svn/reports/inherited-props.c (original)
+++ subversion/branches/ev2-export/subversion/mod_dav_svn/reports/inherited-props.c Tue Dec  4 02:26:18 2012
@@ -113,7 +113,7 @@ dav_svn__get_inherited_props_report(cons
                                 "couldn't retrieve revision root",
                                 resource->pool);
 
-  serr = svn_repos_fs_get_inherited_props(&inherited_props, root, path,
+  serr = svn_repos_fs_get_inherited_props(&inherited_props, root, path, NULL,
                                           dav_svn__authz_read_func(&arb),
                                           &arb, resource->pool, iterpool);
   if (serr)



Mime
View raw message