subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pbu...@apache.org
Subject svn commit: r1312074 - in /subversion/branches/inheritable-props/subversion: include/ include/private/ libsvn_ra/ libsvn_ra_local/ libsvn_ra_neon/ libsvn_ra_serf/ libsvn_ra_svn/ mod_dav_svn/ mod_dav_svn/reports/ svnserve/
Date Wed, 11 Apr 2012 02:33:45 GMT
Author: pburba
Date: Wed Apr 11 02:33:44 2012
New Revision: 1312074

URL: http://svn.apache.org/viewvc?rev=1312074&view=rev
Log:
On the inheritable-props branch: Add a dedicated API for getting
inherited properties & finish implementation of inherited property retrieval
via ra_neon and ra_serf.

* subversion/include/private/svn_dav_protocol.h
  (SVN_DAV__INHERITED_PROPS_REPORT): New custom report.

  (SVN_DAV__IPROP_ITEM,
   SVN_DAV__IPROP_PATH,
   SVN_DAV__IPROP_PROPNAME,
   SVN_DAV__IPROP_PROPVAL): New child elements for new report.

* subversion/include/svn_ra.h
  (svn_ra_get_inherited_props): New.

* subversion/libsvn_ra/ra_loader.c
  (svn_ra_get_inherited_props): New.

* subversion/libsvn_ra/ra_loader.h
  (svn_ra__vtable_t.get_inherited_props): New.

* subversion/libsvn_ra_local/ra_plugin.c
  (get_node_props): Handle case where caller wants only inherited props.

  (svn_ra_local__get_inherited_props): New.

  (ra_local_vtable): Add svn_ra_local__get_inherited_props callback.

* subversion/libsvn_ra_neon/fetch.c
  (svn_ra_neon__get_file,
   svn_ra_neon__get_dir): Actually implement retrieval of inherited props,
   which till now was only promised.

* subversion/libsvn_ra_neon/inherited_props.c: New, ra_neon implementation
  of svn_ra_get_inherited_props.

* subversion/libsvn_ra_neon/ra_neon.h
  (svn_ra_neon__get_inherited_props): New.

  (ELEM_iprop_report,
   ELEM_iprop_item,
   ELEM_iprop_path,
   ELEM_iprop_propname,
   ELEM_iprop_propval): New enums.

* subversion/libsvn_ra_neon/session.c
  (neon_vtable): Add svn_ra_neon__get_inherited_props.

* subversion/libsvn_ra_serf/inherited_props.c: New, ra_serf implementation
  of svn_ra_get_inherited_props.

* subversion/libsvn_ra_serf/ra_serf.h
  (svn_ra_serf__get_inherited_props): New.

* subversion/libsvn_ra_serf/serf.c
  (svn_ra_serf__get_dir): Implement retrieval of inherited props via new
   svn_ra_get_inherited_props API.

* subversion/libsvn_ra_serf/update.c
  (svn_ra_serf__get_file): Implement retrieval of inherited props via new
   svn_ra_get_inherited_props API.

* subversion/libsvn_ra_svn/client.c
  (parse_iproplist): Depth-first ordering of inherited property array was
   fixed in r1312073, so stop fixing it here. 

* subversion/mod_dav_svn/dav_svn.h
  (dav_svn__reports_list): Add SVN_DAV__INHERITED_PROPS_REPORT.

  (dav_svn__get_inherited_props_report): New.

* subversion/mod_dav_svn/reports/inherited-props.c: New, report handler
  for querying inherited props.

* subversion/mod_dav_svn/version.c
  (deliver_report): Handle new report.

* subversion/svnserve/serve.c
  (get_props): Allow callers to ask only for inherited props.

  (get_inherited_props): New.

  (main_commands): Add get_inherited_props.

Added:
    subversion/branches/inheritable-props/subversion/libsvn_ra_neon/inherited_props.c   (with props)
    subversion/branches/inheritable-props/subversion/libsvn_ra_serf/inherited_props.c   (with props)
    subversion/branches/inheritable-props/subversion/mod_dav_svn/reports/inherited-props.c   (with props)
Modified:
    subversion/branches/inheritable-props/subversion/include/private/svn_dav_protocol.h
    subversion/branches/inheritable-props/subversion/include/svn_ra.h
    subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.c
    subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.h
    subversion/branches/inheritable-props/subversion/libsvn_ra_local/ra_plugin.c
    subversion/branches/inheritable-props/subversion/libsvn_ra_neon/fetch.c
    subversion/branches/inheritable-props/subversion/libsvn_ra_neon/ra_neon.h
    subversion/branches/inheritable-props/subversion/libsvn_ra_neon/session.c
    subversion/branches/inheritable-props/subversion/libsvn_ra_serf/ra_serf.h
    subversion/branches/inheritable-props/subversion/libsvn_ra_serf/serf.c
    subversion/branches/inheritable-props/subversion/libsvn_ra_serf/update.c
    subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c
    subversion/branches/inheritable-props/subversion/mod_dav_svn/dav_svn.h
    subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c
    subversion/branches/inheritable-props/subversion/svnserve/serve.c

Modified: subversion/branches/inheritable-props/subversion/include/private/svn_dav_protocol.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/include/private/svn_dav_protocol.h?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/include/private/svn_dav_protocol.h (original)
+++ subversion/branches/inheritable-props/subversion/include/private/svn_dav_protocol.h Wed Apr 11 02:33:44 2012
@@ -33,6 +33,7 @@ extern "C" {
 /** Names for the custom HTTP REPORTs understood by mod_dav_svn, sans
     namespace. */
 #define SVN_DAV__MERGEINFO_REPORT "mergeinfo-report"
+#define SVN_DAV__INHERITED_PROPS_REPORT "inherited-props-report"
 
 /** Names for XML child elements of the custom HTTP REPORTs understood
     by mod_dav_svn, sans namespace. */
@@ -45,6 +46,10 @@ extern "C" {
 #define SVN_DAV__REVISION "revision"
 #define SVN_DAV__INCLUDE_DESCENDANTS "include-descendants"
 #define SVN_DAV__VERSION_NAME "version-name"
+#define SVN_DAV__IPROP_ITEM "iprop-item"
+#define SVN_DAV__IPROP_PATH "iprop-path"
+#define SVN_DAV__IPROP_PROPNAME "iprop-propname"
+#define SVN_DAV__IPROP_PROPVAL "iprop-propval"
 
 /** Names of XML elements attributes and tags for svn_ra_change_rev_prop2()'s
     extension of PROPPATCH.  */

Modified: subversion/branches/inheritable-props/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/include/svn_ra.h?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/include/svn_ra.h (original)
+++ subversion/branches/inheritable-props/subversion/include/svn_ra.h Wed Apr 11 02:33:44 2012
@@ -1950,6 +1950,24 @@ svn_ra_get_deleted_rev(svn_ra_session_t 
                        apr_pool_t *pool);
 
 /**
+ * Set @a *inherited_props to a depth-first ordered array of
+ * #svn_prop_inherited_item_t * structures representing the properties
+ * inherited by @a path at @a revision (or the 'head' revision if
+ * @a revision is @c SVN_INVALID_REVNUM).  Interpret @a path relative to
+ * the URL in @a session.  Use @a pool for all allocations.  If no
+ * inheritable properties are found, then set @a *inherited_props to
+ * an empty array.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_ra_get_inherited_props(svn_ra_session_t *session,
+                           apr_array_header_t **inherited_props,
+                           const char *path,
+                           svn_revnum_t revision,
+                           apr_pool_t *pool);
+
+/**
  * @defgroup Capabilities Dynamically query the server's capabilities.
  *
  * @{

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.c Wed Apr 11 02:33:44 2012
@@ -1385,6 +1385,31 @@ svn_ra_get_deleted_rev(svn_ra_session_t 
   return err;
 }
 
+svn_error_t *
+svn_ra_get_inherited_props(svn_ra_session_t *session,
+                           apr_array_header_t **iprops,
+                           const char *path,
+                           svn_revnum_t revision,
+                           apr_pool_t *pool)
+{
+  svn_boolean_t iprop_capable;
+
+  /* Path must be relative. */
+  SVN_ERR_ASSERT(*path != '/');
+
+  SVN_ERR(svn_ra_has_capability(session, &iprop_capable,
+                                SVN_RA_CAPABILITY_INHERITED_PROPS, pool));
+
+  if (iprop_capable)
+    return svn_error_trace(session->vtable->get_inherited_props(session,
+                                                                iprops,
+                                                                path,
+                                                                revision,
+                                                                pool));
+  /* Fallback for legacy servers. */
+  return svn_error_trace(get_inherited_props(session, path, revision,
+                                             iprops, pool));
+}
 
 
 svn_error_t *

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.h?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra/ra_loader.h Wed Apr 11 02:33:44 2012
@@ -297,7 +297,12 @@ typedef struct svn_ra__vtable_t {
                                   apr_pool_t *pool);
   svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
                                     svn_delta_shim_callbacks_t *callbacks);
-
+  /* See svn_ra_get_inherited_props(). */
+  svn_error_t *(*get_inherited_props)(svn_ra_session_t *session,
+                                      apr_array_header_t **iprops,
+                                      const char *path,
+                                      svn_revnum_t revision,
+                                      apr_pool_t *pool);
 } svn_ra__vtable_t;
 
 /* The RA session object. */

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_local/ra_plugin.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_local/ra_plugin.c Wed Apr 11 02:33:44 2012
@@ -1040,28 +1040,31 @@ get_node_props(apr_hash_t **props,
 
   /* Now add some non-tweakable metadata to the hash as well... */
 
-  /* The so-called 'entryprops' with info about CR & friends. */
-  SVN_ERR(svn_repos_get_committed_info(&cmt_rev, &cmt_date,
-                                       &cmt_author, root, path, pool));
-
-  apr_hash_set(*props,
-               SVN_PROP_ENTRY_COMMITTED_REV,
-               APR_HASH_KEY_STRING,
-               svn_string_createf(pool, "%ld", cmt_rev));
-  apr_hash_set(*props,
-               SVN_PROP_ENTRY_COMMITTED_DATE,
-               APR_HASH_KEY_STRING,
-               cmt_date ? svn_string_create(cmt_date, pool) : NULL);
-  apr_hash_set(*props,
-               SVN_PROP_ENTRY_LAST_AUTHOR,
-               APR_HASH_KEY_STRING,
-               cmt_author ? svn_string_create(cmt_author, pool) : NULL);
-  apr_hash_set(*props,
-               SVN_PROP_ENTRY_UUID,
-               APR_HASH_KEY_STRING,
-               svn_string_create(sess->uuid, pool));
+  if (props)
+    {
+      /* The so-called 'entryprops' with info about CR & friends. */
+      SVN_ERR(svn_repos_get_committed_info(&cmt_rev, &cmt_date,
+                                           &cmt_author, root, path, pool));
+
+      apr_hash_set(*props,
+                   SVN_PROP_ENTRY_COMMITTED_REV,
+                   APR_HASH_KEY_STRING,
+                   svn_string_createf(pool, "%ld", cmt_rev));
+      apr_hash_set(*props,
+                   SVN_PROP_ENTRY_COMMITTED_DATE,
+                   APR_HASH_KEY_STRING,
+                   cmt_date ? svn_string_create(cmt_date, pool) : NULL);
+      apr_hash_set(*props,
+                   SVN_PROP_ENTRY_LAST_AUTHOR,
+                   APR_HASH_KEY_STRING,
+                   cmt_author ? svn_string_create(cmt_author, pool) : NULL);
+      apr_hash_set(*props,
+                   SVN_PROP_ENTRY_UUID,
+                   APR_HASH_KEY_STRING,
+                   svn_string_create(sess->uuid, pool));
 
-  /* We have no 'wcprops' in ra_local, but might someday. */
+      /* We have no 'wcprops' in ra_local, but might someday. */  
+    }
 
   return SVN_NO_ERROR;
 }
@@ -1527,6 +1530,41 @@ svn_ra_local__get_deleted_rev(svn_ra_ses
 }
 
 static svn_error_t *
+svn_ra_local__get_inherited_props(svn_ra_session_t *session,
+                                  apr_array_header_t **iprops,
+                                  const char *path,
+                                  svn_revnum_t revision,
+                                  apr_pool_t *pool)
+{
+  svn_fs_root_t *root;
+  svn_revnum_t youngest_rev;
+  svn_ra_local__session_baton_t *sess = session->priv;
+  const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
+  svn_node_kind_t node_kind;
+
+  /* Open the revision's root. */
+  if (! SVN_IS_VALID_REVNUM(revision))
+    {
+      SVN_ERR(svn_fs_youngest_rev(&youngest_rev, sess->fs, pool));
+      SVN_ERR(svn_fs_revision_root(&root, sess->fs, youngest_rev, pool));
+    }
+  else
+    {
+      SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, pool));
+    }
+
+  SVN_ERR(svn_fs_check_path(&node_kind, root, abs_path, pool));
+  if (node_kind == svn_node_none)
+    {
+      return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
+                               _("'%s' path not found"), abs_path);
+    }
+
+  return svn_error_trace(get_node_props(NULL, iprops, sess, root, abs_path,
+                                        pool));
+}
+
+static svn_error_t *
 svn_ra_local__register_editor_shim_callbacks(svn_ra_session_t *session,
                                     svn_delta_shim_callbacks_t *callbacks)
 {
@@ -1582,7 +1620,8 @@ static const svn_ra__vtable_t ra_local_v
   svn_ra_local__has_capability,
   svn_ra_local__replay_range,
   svn_ra_local__get_deleted_rev,
-  svn_ra_local__register_editor_shim_callbacks
+  svn_ra_local__register_editor_shim_callbacks,
+  svn_ra_local__get_inherited_props
 };
 
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_neon/fetch.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_neon/fetch.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_neon/fetch.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_neon/fetch.c Wed Apr 11 02:33:44 2012
@@ -773,6 +773,24 @@ svn_error_t *svn_ra_neon__get_file(svn_r
         }
     }
 
+  if (inherited_props)
+    {
+      svn_boolean_t supports_iprops;
+
+      SVN_ERR(svn_ra_neon__has_capability(session, &supports_iprops,
+                                          SVN_RA_CAPABILITY_INHERITED_PROPS,
+                                          pool));
+      if (!supports_iprops)
+        {
+          *inherited_props = NULL;
+        }
+      else
+        {
+          SVN_ERR(svn_ra_neon__get_inherited_props(session, inherited_props,
+                                                   path, revision, pool));
+        }
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1060,6 +1078,24 @@ svn_error_t *svn_ra_neon__get_dir(svn_ra
       SVN_ERR(filter_props(*props, rsrc, TRUE, pool));
     }
 
+  if (inherited_props)
+    {
+      svn_boolean_t supports_iprops;
+
+      SVN_ERR(svn_ra_neon__has_capability(session, &supports_iprops,
+                                          SVN_RA_CAPABILITY_INHERITED_PROPS,
+                                          pool));
+      if (!supports_iprops)
+        {
+          *inherited_props = NULL;
+        }
+      else
+        {
+          SVN_ERR(svn_ra_neon__get_inherited_props(session, inherited_props,
+                                                   path, revision, pool));
+        }
+    }
+
   return SVN_NO_ERROR;
 }
 

Added: subversion/branches/inheritable-props/subversion/libsvn_ra_neon/inherited_props.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_neon/inherited_props.c?rev=1312074&view=auto
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_neon/inherited_props.c (added)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_neon/inherited_props.c Wed Apr 11 02:33:44 2012
@@ -0,0 +1,290 @@
+/*
+ * inherited_props.c : ra_neon implementation of svn_ra_get_inherited_props
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+
+#include <apr_pools.h>
+#include <apr_tables.h>
+#include <apr_strings.h>
+#include <apr_xml.h>
+
+#include <ne_socket.h>
+
+#include "svn_error.h"
+#include "svn_pools.h"
+#include "svn_path.h"
+#include "svn_xml.h"
+#include "svn_props.h"
+#include "svn_base64.h"
+#include "private/svn_dav_protocol.h"
+#include "../libsvn_ra/ra_loader.h"
+
+#include "ra_neon.h"
+
+
+/* Our parser states. */
+static const svn_ra_neon__xml_elm_t iprops_report_elements[] =
+  {
+    { SVN_XML_NAMESPACE, SVN_DAV__INHERITED_PROPS_REPORT,
+      ELEM_iprop_report, 0 },
+    { SVN_XML_NAMESPACE, SVN_DAV__IPROP_ITEM,
+      ELEM_iprop_item, 0 },
+    { SVN_XML_NAMESPACE, SVN_DAV__IPROP_PATH,
+      ELEM_iprop_path, SVN_RA_NEON__XML_CDATA },
+    { SVN_XML_NAMESPACE, SVN_DAV__IPROP_PROPNAME,
+      ELEM_iprop_propname, SVN_RA_NEON__XML_CDATA },
+    { SVN_XML_NAMESPACE, SVN_DAV__IPROP_PROPVAL,
+      ELEM_iprop_propval, SVN_RA_NEON__XML_CDATA },
+    { NULL }
+  };
+
+/* Struct for accumulating inherited props. */
+
+typedef struct inherited_props_baton
+{
+  /* The depth-first ordered array of svn_prop_inherited_item_t *
+     structures we are building. */
+  apr_array_header_t *iprops;
+
+  /* Pool in which to allocate elements of IPROPS. */
+  apr_pool_t *pool;
+
+  /* The repository's root URL. */
+  const char *repos_root_url;
+
+  /* Current CDATA values*/
+  svn_stringbuf_t *curr_path;
+  svn_stringbuf_t *curr_propname;
+  svn_stringbuf_t *curr_propval;
+  const char *curr_prop_val_encoding;
+
+  /* Current element in IPROPS. */
+  svn_prop_inherited_item_t *curr_iprop;
+} inherited_props_baton;
+
+
+static svn_error_t *
+start_element(int *elem,
+              void *baton,
+              int parent_state,
+              const char *nspace,
+              const char *elt_name,
+              const char **atts)
+{
+  inherited_props_baton *iprops_baton = baton;
+
+  const svn_ra_neon__xml_elm_t *elm
+    = svn_ra_neon__lookup_xml_elem(iprops_report_elements, nspace,
+                                   elt_name);
+  if (! elm)
+    {
+      *elem = NE_XML_DECLINE;
+      return SVN_NO_ERROR;
+    }
+
+  if (parent_state == ELEM_root)
+    {
+      /* If we're at the root of the tree, the element has to be the editor
+         report itself. */
+      if (elm->id != ELEM_iprop_report)
+        return UNEXPECTED_ELEMENT(nspace, elt_name);
+    }
+  else if (elm->id == ELEM_iprop_item)
+    {
+      svn_stringbuf_setempty(iprops_baton->curr_path);
+      svn_stringbuf_setempty(iprops_baton->curr_propname);
+      svn_stringbuf_setempty(iprops_baton->curr_propval);
+      iprops_baton->curr_prop_val_encoding = NULL;
+      iprops_baton->curr_iprop = NULL;
+    }
+  else if (elm->id == ELEM_iprop_propval)
+    {
+      const char *prop_val_encoding = svn_xml_get_attr_value("encoding",
+                                                             atts);
+      iprops_baton->curr_prop_val_encoding = apr_pstrdup(iprops_baton->pool,
+                                                         prop_val_encoding);
+    }
+
+  *elem = elm->id;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+end_element(void *baton,
+            int state,
+            const char *nspace,
+            const char *elt_name)
+{
+  inherited_props_baton *iprops_baton = baton;
+
+  const svn_ra_neon__xml_elm_t *elm
+    = svn_ra_neon__lookup_xml_elem(iprops_report_elements, nspace,
+                                   elt_name);
+  if (! elm)
+    return UNEXPECTED_ELEMENT(nspace, elt_name);
+
+  if (elm->id == ELEM_iprop_path)
+    {
+      iprops_baton->curr_iprop = apr_palloc(
+        iprops_baton->pool, sizeof(svn_prop_inherited_item_t));
+
+      iprops_baton->curr_iprop->path_or_url =
+        svn_path_url_add_component2(iprops_baton->repos_root_url,
+                                    iprops_baton->curr_path->data,
+                                    iprops_baton->pool);
+      iprops_baton->curr_iprop->prop_hash = apr_hash_make(iprops_baton->pool);
+    }
+  else if (elm->id == ELEM_iprop_propval)
+    {
+      const svn_string_t *prop_val;
+
+      if (iprops_baton->curr_prop_val_encoding)
+        {
+          svn_string_t encoded_prop_val;
+
+          if (strcmp(iprops_baton->curr_prop_val_encoding, "base64") != 0)
+            return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+          encoded_prop_val.data = iprops_baton->curr_propval->data;
+          encoded_prop_val.len = iprops_baton->curr_propval->len;
+          prop_val = svn_base64_decode_string(&encoded_prop_val,
+                                              iprops_baton->pool);
+        }
+      else
+        {
+          prop_val = svn_string_create_from_buf(iprops_baton->curr_propval,
+                                                iprops_baton->pool);
+        }
+
+      apr_hash_set(iprops_baton->curr_iprop->prop_hash,
+                   apr_pstrdup(iprops_baton->pool,
+                               iprops_baton->curr_propname->data),
+                   APR_HASH_KEY_STRING,
+                   prop_val);
+
+      /* Clear current propname and propval in the event there are
+         multiple properties on the current path. */
+      svn_stringbuf_setempty(iprops_baton->curr_propname);
+      svn_stringbuf_setempty(iprops_baton->curr_propval);
+    } 
+  else if (elm->id == ELEM_iprop_item)
+    {
+      APR_ARRAY_PUSH(iprops_baton->iprops, svn_prop_inherited_item_t *) =
+        iprops_baton->curr_iprop;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+cdata_handler(void *baton, int state, const char *cdata, size_t len)
+{
+  inherited_props_baton *iprops_baton = baton;
+  apr_size_t nlen = len;
+
+  switch (state)
+    {
+    case ELEM_iprop_path:
+      svn_stringbuf_appendbytes(iprops_baton->curr_path, cdata, nlen);
+      break;
+
+    case ELEM_iprop_propname:
+      svn_stringbuf_appendbytes(iprops_baton->curr_propname, cdata, nlen);
+      break;
+
+    case ELEM_iprop_propval:
+      svn_stringbuf_appendbytes(iprops_baton->curr_propval, cdata, nlen);
+      break;
+
+    default:
+      break;
+    }
+  return SVN_NO_ERROR;
+}
+
+/* Request a mergeinfo-report from the URL attached to SESSION,
+   and fill in the CATALOG with the results.  */
+svn_error_t *
+svn_ra_neon__get_inherited_props(svn_ra_session_t *session,
+                                 apr_array_header_t **iprops,
+                                 const char *path,
+                                 svn_revnum_t revision,
+                                 apr_pool_t *pool)
+{
+  svn_ra_neon__session_t *ras = session->priv;
+  svn_stringbuf_t *request_body = svn_stringbuf_create_empty(pool);
+  inherited_props_baton iprops_baton;
+  const char *bc_url;
+  const char *bc_relative;
+  const char *final_bc_url;
+  static const char iprops_report_head[] =
+    "<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR
+    "<S:" SVN_DAV__INHERITED_PROPS_REPORT " xmlns:S=\""
+    SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR;
+
+  static const char iprops_report_tail[] =
+    "</S:" SVN_DAV__INHERITED_PROPS_REPORT ">" DEBUG_CR;
+
+  /* Construct the request body. */
+  svn_stringbuf_appendcstr(request_body, iprops_report_head);
+  svn_stringbuf_appendcstr(request_body,
+                           apr_psprintf(pool,
+                                        "<S:revision>%ld"
+                                        "</S:revision>" DEBUG_CR, revision));
+  svn_stringbuf_appendcstr(request_body, "<S:path>");
+  svn_stringbuf_appendcstr(request_body, apr_xml_quote_string(pool, path, 0));
+  svn_stringbuf_appendcstr(request_body, "</S:path>");
+
+  svn_stringbuf_appendcstr(request_body, iprops_report_tail);
+  iprops_baton.repos_root_url = ras->repos_root;
+  iprops_baton.pool = pool;
+  iprops_baton.curr_path = svn_stringbuf_create_empty(pool);
+  iprops_baton.curr_propname = svn_stringbuf_create_empty(pool);
+  iprops_baton.curr_propval = svn_stringbuf_create_empty(pool);
+  iprops_baton.curr_iprop = NULL;
+  iprops_baton.iprops = apr_array_make(pool, 1,
+                                       sizeof(svn_prop_inherited_item_t *));
+
+  /* ras's URL may not exist in HEAD, and thus it's not safe to send
+     it as the main argument to the REPORT request; it might cause
+     dav_get_resource() to choke on the server.  So instead, we pass a
+     baseline-collection URL, which we get from END. */
+  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
+                                         ras->url->data, revision, pool));
+  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);
+
+  SVN_ERR(svn_ra_neon__parsed_request(ras,
+                                      "REPORT",
+                                      final_bc_url,
+                                      request_body->data,
+                                      NULL, NULL,
+                                      start_element,
+                                      cdata_handler,
+                                      end_element,
+                                      &iprops_baton,
+                                      NULL,
+                                      NULL,
+                                      FALSE,
+                                      pool));
+  *iprops = iprops_baton.iprops;
+  return SVN_NO_ERROR;
+}

Propchange: subversion/branches/inheritable-props/subversion/libsvn_ra_neon/inherited_props.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_neon/ra_neon.h?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_neon/ra_neon.h Wed Apr 11 02:33:44 2012
@@ -394,6 +394,11 @@ svn_error_t *svn_ra_neon__get_file_revs(
                                         void *handler_baton,
                                         apr_pool_t *pool);
 
+svn_error_t * svn_ra_neon__get_inherited_props(svn_ra_session_t *session,
+                                               apr_array_header_t **iprops,
+                                               const char *path,
+                                               svn_revnum_t revision,
+                                               apr_pool_t *pool);
 
 /* Local duplicate of svn_ra_get_path_relative_to_root(). */
 svn_error_t *svn_ra_neon__get_path_relative_to_root(svn_ra_session_t *session,
@@ -863,7 +868,12 @@ enum {
   ELEM_has_children,
   ELEM_merged_revision,
   ELEM_deleted_rev_report,
-  ELEM_subtractive_merge
+  ELEM_subtractive_merge,
+  ELEM_iprop_report,
+  ELEM_iprop_item,
+  ELEM_iprop_path,
+  ELEM_iprop_propname,
+  ELEM_iprop_propval
 };
 
 /* ### docco */

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_neon/session.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_neon/session.c Wed Apr 11 02:33:44 2012
@@ -1230,7 +1230,8 @@ static const svn_ra__vtable_t neon_vtabl
   svn_ra_neon__has_capability,
   svn_ra_neon__replay_range,
   svn_ra_neon__get_deleted_rev,
-  svn_ra_neon__register_editor_shim_callbacks
+  svn_ra_neon__register_editor_shim_callbacks,
+  svn_ra_neon__get_inherited_props
 };
 
 svn_error_t *

Added: subversion/branches/inheritable-props/subversion/libsvn_ra_serf/inherited_props.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_serf/inherited_props.c?rev=1312074&view=auto
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_serf/inherited_props.c (added)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_serf/inherited_props.c Wed Apr 11 02:33:44 2012
@@ -0,0 +1,349 @@
+/*
+ * inherited_props.c : ra_serf implementation of svn_ra_get_inherited_props
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+
+#include <apr_tables.h>
+#include <apr_xml.h>
+
+#include "svn_path.h"
+#include "svn_ra.h"
+#include "svn_string.h"
+#include "svn_xml.h"
+#include "svn_props.h"
+#include "svn_base64.h"
+
+#include "private/svn_dav_protocol.h"
+#include "../libsvn_ra/ra_loader.h"
+#include "svn_private_config.h"
+#include "ra_serf.h"
+
+
+/* The current state of our XML parsing. */
+typedef enum iprops_state_e {
+  NONE = 0,
+  IPROPS_REPORT,
+  IPROPS_ITEM,
+  IPROPS_PATH,
+  IPROPS_PROPNAME,
+  IPROPS_PROPVAL
+} iprops_state_e;
+
+/* Struct for accumulating inherited props. */
+typedef struct iprops_context_t {
+  /* The depth-first ordered array of svn_prop_inherited_item_t *
+     structures we are building. */
+  apr_array_header_t *iprops;
+
+  /* Pool in which to allocate elements of IPROPS. */
+  apr_pool_t *pool;
+
+  /* The repository's root URL. */
+  const char *repos_root_url;
+
+  /* Current CDATA values*/
+  svn_stringbuf_t *curr_path;
+  svn_stringbuf_t *curr_propname;
+  svn_stringbuf_t *curr_propval;
+  const char *curr_prop_val_encoding;
+
+  /* Current element in IPROPS. */
+  svn_prop_inherited_item_t *curr_iprop;
+
+  /* Serf context completion flag for svn_ra_serf__context_run_wait() */
+  svn_boolean_t done;
+
+  /* Path we are finding inherited properties for.  This is relative to
+     the RA session passed to svn_ra_serf__get_inherited_props. */
+  const char *path;
+  /* The revision of PATH*/
+  svn_revnum_t revision;
+} iprops_context_t;
+
+static svn_error_t *
+start_element(svn_ra_serf__xml_parser_t *parser,
+              svn_ra_serf__dav_props_t name,
+              const char **attrs,
+              apr_pool_t *scratch_pool)
+{
+  iprops_context_t *iprops_ctx = parser->user_data;
+  iprops_state_e state;
+
+  state = parser->state->current_state;
+  if (state == NONE
+      && strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_REPORT);
+    }
+  else if (state == IPROPS_REPORT &&
+           strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0)
+    {
+      svn_stringbuf_setempty(iprops_ctx->curr_path);
+      svn_stringbuf_setempty(iprops_ctx->curr_propname);
+      svn_stringbuf_setempty(iprops_ctx->curr_propval);
+      iprops_ctx->curr_prop_val_encoding = NULL;
+      iprops_ctx->curr_iprop = NULL;
+      svn_ra_serf__xml_push_state(parser, IPROPS_ITEM);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
+    {
+      const char *prop_val_encoding = svn_xml_get_attr_value("encoding",
+                                                             attrs);
+      iprops_ctx->curr_prop_val_encoding = apr_pstrdup(iprops_ctx->pool,
+                                                       prop_val_encoding);
+      svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PATH) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_PATH);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_PROPNAME);
+    }
+  else if (state == IPROPS_ITEM &&
+           strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
+    {
+      svn_ra_serf__xml_push_state(parser, IPROPS_PROPVAL);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+end_element(svn_ra_serf__xml_parser_t *parser,
+            svn_ra_serf__dav_props_t name,
+            apr_pool_t *scratch_pool)
+{
+  iprops_context_t *iprops_ctx = parser->user_data;
+  iprops_state_e state;
+
+  state = parser->state->current_state;
+
+    if (state == IPROPS_REPORT &&
+      strcmp(name.name, SVN_DAV__INHERITED_PROPS_REPORT) == 0)
+    {
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_PATH
+           && strcmp(name.name, SVN_DAV__IPROP_PATH) == 0)
+    {
+      iprops_ctx->curr_iprop = apr_palloc(
+        iprops_ctx->pool, sizeof(svn_prop_inherited_item_t));
+
+      iprops_ctx->curr_iprop->path_or_url =
+        svn_path_url_add_component2(iprops_ctx->repos_root_url,
+                                    iprops_ctx->curr_path->data,
+                                    iprops_ctx->pool);
+      iprops_ctx->curr_iprop->prop_hash = apr_hash_make(iprops_ctx->pool);
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_PROPVAL
+           && strcmp(name.name, SVN_DAV__IPROP_PROPVAL) == 0)
+    {
+      const svn_string_t *prop_val;
+
+      if (iprops_ctx->curr_prop_val_encoding)
+        {
+          svn_string_t encoded_prop_val;
+
+          if (strcmp(iprops_ctx->curr_prop_val_encoding, "base64") != 0)
+            return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL);
+
+          encoded_prop_val.data = iprops_ctx->curr_propval->data;
+          encoded_prop_val.len = iprops_ctx->curr_propval->len;
+          prop_val = svn_base64_decode_string(&encoded_prop_val,
+                                              iprops_ctx->pool);
+        }
+      else
+        {
+          prop_val = svn_string_create_from_buf(iprops_ctx->curr_propval,
+                                                iprops_ctx->pool);
+        }
+
+      apr_hash_set(iprops_ctx->curr_iprop->prop_hash,
+                   apr_pstrdup(iprops_ctx->pool,
+                               iprops_ctx->curr_propname->data),
+                   APR_HASH_KEY_STRING,
+                   prop_val);
+      /* Clear current propname and propval in the event there are
+         multiple properties on the current path. */
+      svn_stringbuf_setempty(iprops_ctx->curr_propname);
+      svn_stringbuf_setempty(iprops_ctx->curr_propval);
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_PROPNAME
+           && strcmp(name.name, SVN_DAV__IPROP_PROPNAME) == 0)
+    {
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  else if (state == IPROPS_ITEM
+           && strcmp(name.name, SVN_DAV__IPROP_ITEM) == 0)
+    {
+      APR_ARRAY_PUSH(iprops_ctx->iprops, svn_prop_inherited_item_t *) =
+        iprops_ctx->curr_iprop;
+      svn_ra_serf__xml_pop_state(parser);
+    }
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+cdata_handler(svn_ra_serf__xml_parser_t *parser,
+              const char *data,
+              apr_size_t len,
+              apr_pool_t *scratch_pool)
+{
+  iprops_context_t *iprops_ctx = parser->user_data;
+  iprops_state_e state = parser->state->current_state;
+
+  switch (state)
+    {
+    case IPROPS_PATH:
+      svn_stringbuf_appendbytes(iprops_ctx->curr_path, data, len);
+      break;
+
+    case IPROPS_PROPNAME:
+      svn_stringbuf_appendbytes(iprops_ctx->curr_propname, data, len);
+      break;
+
+    case IPROPS_PROPVAL:
+      svn_stringbuf_appendbytes(iprops_ctx->curr_propval, data, len);
+      break;
+
+    default:
+      break;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+create_iprops_body(serf_bucket_t **bkt,
+                   void *baton,
+                   serf_bucket_alloc_t *alloc,
+                   apr_pool_t *pool)
+{
+  iprops_context_t *iprops_ctx = baton;
+  serf_bucket_t *body_bkt;
+
+  body_bkt = serf_bucket_aggregate_create(alloc);
+
+  svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+                                    "S:" SVN_DAV__INHERITED_PROPS_REPORT,
+                                    "xmlns:S", SVN_XML_NAMESPACE,
+                                    NULL);
+  svn_ra_serf__add_tag_buckets(body_bkt,
+                               "S:" SVN_DAV__REVISION,
+                               apr_ltoa(pool, iprops_ctx->revision),
+                               alloc);
+  svn_ra_serf__add_tag_buckets(body_bkt, "S:" SVN_DAV__PATH,
+                               iprops_ctx->path, alloc);
+  svn_ra_serf__add_close_tag_buckets(body_bkt, alloc,
+                                     "S:" SVN_DAV__INHERITED_PROPS_REPORT);
+  *bkt = body_bkt;
+  return SVN_NO_ERROR;
+}
+
+/* Request a mergeinfo-report from the URL attached to SESSION,
+   and fill in the MERGEINFO hash with the results.  */
+svn_error_t *
+svn_ra_serf__get_inherited_props(svn_ra_session_t *ra_session,
+                                 apr_array_header_t **iprops,
+                                 const char *path,
+                                 svn_revnum_t revision,
+                                 apr_pool_t *pool)
+{
+  svn_error_t *err, *err2;
+  int status_code;
+
+  iprops_context_t *iprops_ctx;
+  svn_ra_serf__session_t *session = ra_session->priv;
+  svn_ra_serf__handler_t *handler;
+  svn_ra_serf__xml_parser_t *parser_ctx;
+  const char *relative_url, *basecoll_url;
+  const char *target_url;
+
+  SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
+                                         session, NULL, NULL, revision, NULL,
+                                         pool));
+
+  target_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
+
+  iprops_ctx = apr_pcalloc(pool, sizeof(*iprops_ctx));
+  iprops_ctx->done = FALSE;
+  iprops_ctx->repos_root_url = session->repos_root_str;
+  iprops_ctx->pool = pool;
+  iprops_ctx->curr_path = svn_stringbuf_create_empty(pool);
+  iprops_ctx->curr_propname = svn_stringbuf_create_empty(pool);
+  iprops_ctx->curr_propval = svn_stringbuf_create_empty(pool);
+  iprops_ctx->curr_iprop = NULL;
+  iprops_ctx->iprops = apr_array_make(pool, 1,
+                                       sizeof(svn_prop_inherited_item_t *));
+  iprops_ctx->path = path;
+  iprops_ctx->revision = revision;
+
+  handler = apr_pcalloc(pool, sizeof(*handler));
+
+  handler->method = "REPORT";
+  handler->path = target_url;
+  handler->conn = session->conns[0];
+  handler->session = session;
+  handler->body_delegate = create_iprops_body;
+  handler->body_delegate_baton = iprops_ctx;
+  handler->body_type = "text/xml";
+
+  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
+
+  parser_ctx->pool = pool;
+  parser_ctx->user_data = iprops_ctx;
+  parser_ctx->start = start_element;
+  parser_ctx->end = end_element;
+  parser_ctx->cdata = cdata_handler;
+  parser_ctx->done = &iprops_ctx->done;
+  parser_ctx->status_code = &status_code;
+
+  handler->response_handler = svn_ra_serf__handle_xml_parser;
+  handler->response_baton = parser_ctx;
+
+  svn_ra_serf__request_create(handler);
+
+  err = svn_ra_serf__context_run_wait(&iprops_ctx->done, session, pool);
+
+  err2 = svn_ra_serf__error_on_status(status_code, handler->path,
+                                      parser_ctx->location);
+  if (err2)
+    {
+      svn_error_clear(err);
+      return err2;
+    }
+
+  SVN_ERR(err);
+
+  if (iprops_ctx->done)
+    *iprops = iprops_ctx->iprops;
+
+  return SVN_NO_ERROR;
+}

Propchange: subversion/branches/inheritable-props/subversion/libsvn_ra_serf/inherited_props.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_serf/ra_serf.h?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_serf/ra_serf.h Wed Apr 11 02:33:44 2012
@@ -1383,6 +1383,13 @@ svn_ra_serf__get_deleted_rev(svn_ra_sess
                              svn_revnum_t *revision_deleted,
                              apr_pool_t *pool);
 
+/* Implements the get_inherited_props RA layer function. */
+svn_error_t * svn_ra_serf__get_inherited_props(svn_ra_session_t *session,
+                                               apr_array_header_t **iprops,
+                                               const char *path,
+                                               svn_revnum_t revision,
+                                               apr_pool_t *pool);
+
 /*** Authentication handler declarations ***/
 
 /**

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_serf/serf.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_serf/serf.c Wed Apr 11 02:33:44 2012
@@ -956,12 +956,13 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
                      apr_hash_t **ret_props,
                      apr_array_header_t **inherited_props,
                      const char *rel_path,
-                     svn_revnum_t revision,
+                     svn_revnum_t peg_rev,
                      apr_uint32_t dirent_fields,
                      apr_pool_t *pool)
 {
   svn_ra_serf__session_t *session = ra_session->priv;
   const char *path;
+  svn_revnum_t revision = peg_rev;
 
   path = session->session_url.path;
 
@@ -1061,6 +1062,24 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
                                          pool, pool));
     }
 
+  if (inherited_props)
+    {
+      svn_boolean_t supports_iprops;
+
+      SVN_ERR(svn_ra_serf__has_capability(ra_session, &supports_iprops,
+                                          SVN_RA_CAPABILITY_INHERITED_PROPS,
+                                          pool));
+      if (!supports_iprops)
+        {
+          *inherited_props = NULL;
+        }
+      else
+        {
+          SVN_ERR(svn_ra_serf__get_inherited_props(ra_session, inherited_props,
+                                                   rel_path, peg_rev, pool));
+        }
+    }
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_serf/update.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_serf/update.c Wed Apr 11 02:33:44 2012
@@ -2772,7 +2772,7 @@ svn_ra_serf__do_switch(svn_ra_session_t 
 svn_error_t *
 svn_ra_serf__get_file(svn_ra_session_t *ra_session,
                       const char *path,
-                      svn_revnum_t revision,
+                      svn_revnum_t peg_rev,
                       svn_stream_t *stream,
                       svn_revnum_t *fetched_rev,
                       apr_hash_t **props,
@@ -2784,6 +2784,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
   const char *fetch_url;
   apr_hash_t *fetch_props;
   svn_node_kind_t res_kind;
+  svn_revnum_t revision = peg_rev;
 
   /* What connection should we go on? */
   conn = session->conns[session->cur_conn];
@@ -2862,5 +2863,23 @@ svn_ra_serf__get_file(svn_ra_session_t *
       SVN_ERR(svn_ra_serf__context_run_wait(&stream_ctx->done, session, pool));
     }
 
+  if (inherited_props)
+    {
+      svn_boolean_t supports_iprops;
+
+      SVN_ERR(svn_ra_serf__has_capability(ra_session, &supports_iprops,
+                                          SVN_RA_CAPABILITY_INHERITED_PROPS,
+                                          pool));
+      if (!supports_iprops)
+        {
+          *inherited_props = NULL;
+        }
+      else
+        {
+          SVN_ERR(svn_ra_serf__get_inherited_props(ra_session, inherited_props,
+                                                   path, peg_rev, pool));
+        }
+    }
+
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c Wed Apr 11 02:33:44 2012
@@ -1041,9 +1041,7 @@ parse_iproplist(apr_array_header_t **inh
 
   iterpool = svn_pool_create(scratch_pool);
 
-  /* Iterate backwards over the array to preserve the depth-first ordering
-     of the parent paths as we create *INHERITED_PROPS. */
-  for (i = iproplist->nelts - 1; i >= 0; i--)
+  for (i = 0; i < iproplist->nelts; i++)
     {
       apr_array_header_t *iprop_list;
       char *parent_rel_path;
@@ -2597,6 +2595,26 @@ ra_svn_register_editor_shim_callbacks(sv
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+ra_svn_get_inherited_props(svn_ra_session_t *session,
+                           apr_array_header_t **iprops,
+                           const char *path,
+                           svn_revnum_t revision,
+                           apr_pool_t *pool)
+{
+  svn_ra_svn__session_baton_t *sess_baton = session->priv;
+  svn_ra_svn_conn_t *conn = sess_baton->conn;
+  apr_array_header_t *iproplist;
+
+  SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-iprops", "c(?r)", path,
+                               revision));
+  SVN_ERR(handle_auth_request(sess_baton, pool));
+  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "l", &iproplist));
+  SVN_ERR(parse_iproplist(iprops, iproplist, session, pool, pool));
+  //SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
+
+  return SVN_NO_ERROR;
+}
 
 static const svn_ra__vtable_t ra_svn_vtable = {
   svn_ra_svn_version,
@@ -2634,7 +2652,8 @@ static const svn_ra__vtable_t ra_svn_vta
   ra_svn_has_capability,
   ra_svn_replay_range,
   ra_svn_get_deleted_rev,
-  ra_svn_register_editor_shim_callbacks
+  ra_svn_register_editor_shim_callbacks,
+  ra_svn_get_inherited_props
 };
 
 svn_error_t *

Modified: subversion/branches/inheritable-props/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/mod_dav_svn/dav_svn.h?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/inheritable-props/subversion/mod_dav_svn/dav_svn.h Wed Apr 11 02:33:44 2012
@@ -617,6 +617,7 @@ static const dav_report_elem dav_svn__re
   { SVN_XML_NAMESPACE, "replay-report" },
   { SVN_XML_NAMESPACE, "get-deleted-rev-report" },
   { SVN_XML_NAMESPACE, SVN_DAV__MERGEINFO_REPORT },
+  { SVN_XML_NAMESPACE, SVN_DAV__INHERITED_PROPS_REPORT },
   { NULL, NULL },
 };
 
@@ -664,6 +665,10 @@ dav_svn__get_deleted_rev_report(const da
                                 const apr_xml_doc *doc,
                                 ap_filter_t *output);
 
+dav_error *
+dav_svn__get_inherited_props_report(const dav_resource *resource,
+                                    const apr_xml_doc *doc,
+                                    ap_filter_t *output);
 
 /*** posts/ ***/
 

Added: subversion/branches/inheritable-props/subversion/mod_dav_svn/reports/inherited-props.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/mod_dav_svn/reports/inherited-props.c?rev=1312074&view=auto
==============================================================================
--- subversion/branches/inheritable-props/subversion/mod_dav_svn/reports/inherited-props.c (added)
+++ subversion/branches/inheritable-props/subversion/mod_dav_svn/reports/inherited-props.c Wed Apr 11 02:33:44 2012
@@ -0,0 +1,230 @@
+/*
+ * inherited-props.c: mod_dav_svn REPORT handler for querying inherited props.
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <apr_xml.h>
+
+#include <http_request.h>
+#include <http_log.h>
+#include <mod_dav.h>
+
+#include "svn_pools.h"
+#include "svn_repos.h"
+#include "svn_xml.h"
+#include "svn_path.h"
+#include "svn_dav.h"
+#include "svn_props.h"
+#include "svn_base64.h"
+
+#include "private/svn_fspath.h"
+#include "private/svn_dav_protocol.h"
+#include "private/svn_log.h"
+#include "private/svn_mergeinfo_private.h"
+
+#include "../dav_svn.h"
+
+dav_error *
+dav_svn__get_inherited_props_report(const dav_resource *resource,
+                                    const apr_xml_doc *doc,
+                                    ap_filter_t *output)
+{
+  /* ### IPROS TODO: Subpool */
+  /* ### IPROS TODO: Authz   */
+  svn_error_t *serr;
+  dav_error *derr = NULL;
+  apr_xml_elem *child;
+  apr_array_header_t *inherited_props;
+  dav_svn__authz_read_baton arb;
+  int ns;
+  apr_bucket_brigade *bb;
+  const char *path = "/";
+  svn_fs_root_t *root;
+  int i;
+  svn_revnum_t rev = SVN_INVALID_REVNUM;
+
+  /* Sanity check. */
+  ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
+  if (ns == -1)
+    {
+      return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
+                                    "The request does not contain the 'svn:' "
+                                    "namespace, so it is not going to have "
+                                    "certain required elements.",
+                                    SVN_DAV_ERROR_NAMESPACE,
+                                    SVN_DAV_ERROR_TAG);
+    }
+
+  for (child = doc->root->first_child;
+       child != NULL;
+       child = child->next)
+    {
+      /* if this element isn't one of ours, then skip it */
+      if (child->ns != ns)
+        continue;
+
+      if (strcmp(child->name, SVN_DAV__REVISION) == 0)
+        {
+          rev = SVN_STR_TO_REV(dav_xml_get_cdata(child, resource->pool, 1));
+        }
+      else if (strcmp(child->name, SVN_DAV__PATH) == 0)
+        {
+          path = dav_xml_get_cdata(child, resource->pool, 0);
+          if ((derr = dav_svn__test_canonical(path, resource->pool)))
+            return derr;
+          path = svn_fspath__join(resource->info->repos_path, path,
+                                  resource->pool);
+        }
+      /* else unknown element; skip it */
+    }
+
+  /* Build authz read baton */
+  arb.r = resource->info->r;
+  arb.repos = resource->info->repos;
+
+  /* Build inherited property brigade */
+  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+
+  serr = svn_fs_revision_root(&root, resource->info->repos->fs,
+                              rev, resource->pool);
+  if (serr != NULL)
+    return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                "couldn't retrieve revision root",
+                                resource->pool);
+
+  serr = svn_fs_node_proplist2(NULL, &inherited_props, root, path,
+                               resource->pool, resource->pool);
+
+  if (serr)
+    {
+      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message,
+                                  resource->pool);
+      goto cleanup;
+    }
+
+  serr = dav_svn__brigade_puts(bb, output,
+                               DAV_XML_HEADER DEBUG_CR
+                               "<S:" SVN_DAV__INHERITED_PROPS_REPORT " "
+                               "xmlns:S=\"" SVN_XML_NAMESPACE "\" "
+                               "xmlns:D=\"DAV:\">" DEBUG_CR);
+  if (serr)
+    {
+      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message,
+                                  resource->pool);
+      goto cleanup;
+    }
+
+  for (i = 0; i < inherited_props->nelts; i++)
+    {
+      svn_prop_inherited_item_t *elt =
+        APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
+
+      serr = dav_svn__brigade_printf(
+        bb, output,
+        "<S:" SVN_DAV__IPROP_ITEM ">"
+        DEBUG_CR
+        "<S:" SVN_DAV__IPROP_PATH ">%s</S:" SVN_DAV__IPROP_PATH ">"
+        DEBUG_CR,
+        apr_xml_quote_string(resource->pool, elt->path_or_url, 0));
+
+      if (!serr)
+        {
+          apr_hash_index_t *hi;
+
+          for (hi = apr_hash_first(resource->pool, elt->prop_hash);
+               hi;
+               hi = apr_hash_next(hi))
+            {
+              const char *propname = svn__apr_hash_index_key(hi);
+              svn_string_t *propval = svn__apr_hash_index_val(hi);
+              const char *xml_safe;
+
+              serr = dav_svn__brigade_printf(
+                bb, output,
+                "<S:" SVN_DAV__IPROP_PROPNAME ">%s</S:"
+                SVN_DAV__IPROP_PROPNAME ">" DEBUG_CR,
+                apr_xml_quote_string(resource->pool, propname, 0));
+
+              if (!serr)
+                {
+                  if (svn_xml_is_xml_safe(propval->data, propval->len))
+                    {
+                      svn_stringbuf_t *tmp = NULL;
+                      svn_xml_escape_cdata_string(&tmp, propval,
+                                                  resource->pool);
+                      xml_safe = tmp->data;
+                      serr = dav_svn__brigade_printf(
+                        bb, output,
+                        "<S:" SVN_DAV__IPROP_PROPVAL ">%s</S:"
+                        SVN_DAV__IPROP_PROPVAL ">" DEBUG_CR, xml_safe);
+                    }
+                  else
+                    {
+                      xml_safe = svn_base64_encode_string2(
+                        propval, TRUE, resource->pool)->data;
+                      serr = dav_svn__brigade_printf(
+                        bb, output,
+                        "<S:" SVN_DAV__IPROP_PROPVAL
+                        " encoding=\"base64\"" ">%s</S:"
+                        SVN_DAV__IPROP_PROPVAL ">" DEBUG_CR, xml_safe);
+                    }
+                }
+
+              if (serr)
+                break;              
+            }
+          if (!serr)
+            serr = dav_svn__brigade_printf(bb, output,
+                                           "</S:" SVN_DAV__IPROP_ITEM ">"
+                                           DEBUG_CR);
+        }
+
+      if (serr)
+        {
+          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                      "Error ending REPORT response.",
+                                      resource->pool);
+          goto cleanup;
+        }
+    }
+
+  if ((serr = dav_svn__brigade_puts(bb, output,
+                                    "</S:" SVN_DAV__INHERITED_PROPS_REPORT ">"
+                                    DEBUG_CR)))
+    {
+      derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                  "Error ending REPORT response.",
+                                  resource->pool);
+      goto cleanup;
+    }
+
+ cleanup:
+
+  /* Log this 'high level' svn action. */
+  dav_svn__operational_log(resource->info,
+                           svn_log__get_inherited_props(path, rev,
+                                                        resource->pool));
+
+  return dav_svn__final_flush_or_error(resource->info->r, bb, output,
+                                       derr, resource->pool);
+}

Propchange: subversion/branches/inheritable-props/subversion/mod_dav_svn/reports/inherited-props.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/inheritable-props/subversion/mod_dav_svn/version.c Wed Apr 11 02:33:44 2012
@@ -1094,6 +1094,10 @@ deliver_report(request_rec *r,
         {
           return dav_svn__get_deleted_rev_report(resource, doc, output);
         }
+      else if (strcmp(doc->root->name, SVN_DAV__INHERITED_PROPS_REPORT) == 0)
+        {
+          return dav_svn__get_inherited_props_report(resource, doc, output);
+        }
       /* NOTE: if you add a report, don't forget to add it to the
        *       dav_svn__reports_list[] array.
        */

Modified: subversion/branches/inheritable-props/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/svnserve/serve.c?rev=1312074&r1=1312073&r2=1312074&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/svnserve/serve.c (original)
+++ subversion/branches/inheritable-props/subversion/svnserve/serve.c Wed Apr 11 02:33:44 2012
@@ -962,7 +962,8 @@ static svn_error_t *write_lock(svn_ra_sv
 }
 
 /* ### This really belongs in libsvn_repos. */
-/* Get the properties for a path, with hardcoded committed-info values. */
+/* Get the properties and/or inherited properties for a PATH in ROOT, with
+   hardcoded committed-info values. */
 static svn_error_t *
 get_props(apr_hash_t **props,
           apr_array_header_t **iprops,
@@ -970,29 +971,34 @@ get_props(apr_hash_t **props,
           const char *path,
           apr_pool_t *pool)
 {
-  svn_string_t *str;
-  svn_revnum_t crev;
-  const char *cdate, *cauthor, *uuid;
-
   /* Get the properties. */
   SVN_ERR(svn_fs_node_proplist2(props, iprops, root, path, pool, pool));
 
-  /* Hardcode the values for the committed revision, date, and author. */
-  SVN_ERR(svn_repos_get_committed_info(&crev, &cdate, &cauthor, root,
-                                       path, pool));
-  str = svn_string_create(apr_psprintf(pool, "%ld", crev),
-                          pool);
-  apr_hash_set(*props, SVN_PROP_ENTRY_COMMITTED_REV, APR_HASH_KEY_STRING, str);
-  str = (cdate) ? svn_string_create(cdate, pool) : NULL;
-  apr_hash_set(*props, SVN_PROP_ENTRY_COMMITTED_DATE, APR_HASH_KEY_STRING,
-               str);
-  str = (cauthor) ? svn_string_create(cauthor, pool) : NULL;
-  apr_hash_set(*props, SVN_PROP_ENTRY_LAST_AUTHOR, APR_HASH_KEY_STRING, str);
-
-  /* Hardcode the values for the UUID. */
-  SVN_ERR(svn_fs_get_uuid(svn_fs_root_fs(root), &uuid, pool));
-  str = (uuid) ? svn_string_create(uuid, pool) : NULL;
-  apr_hash_set(*props, SVN_PROP_ENTRY_UUID, APR_HASH_KEY_STRING, str);
+  if (props)
+    {
+      svn_string_t *str;
+      svn_revnum_t crev;
+      const char *cdate, *cauthor, *uuid;
+
+      /* Hardcode the values for the committed revision, date, and author. */
+      SVN_ERR(svn_repos_get_committed_info(&crev, &cdate, &cauthor, root,
+                                           path, pool));
+      str = svn_string_create(apr_psprintf(pool, "%ld", crev),
+                              pool);
+      apr_hash_set(*props, SVN_PROP_ENTRY_COMMITTED_REV, APR_HASH_KEY_STRING,
+                   str);
+      str = (cdate) ? svn_string_create(cdate, pool) : NULL;
+      apr_hash_set(*props, SVN_PROP_ENTRY_COMMITTED_DATE, APR_HASH_KEY_STRING,
+                   str);
+      str = (cauthor) ? svn_string_create(cauthor, pool) : NULL;
+      apr_hash_set(*props, SVN_PROP_ENTRY_LAST_AUTHOR, APR_HASH_KEY_STRING,
+                   str);
+
+      /* Hardcode the values for the UUID. */
+      SVN_ERR(svn_fs_get_uuid(svn_fs_root_fs(root), &uuid, pool));
+      str = (uuid) ? svn_string_create(uuid, pool) : NULL;
+      apr_hash_set(*props, SVN_PROP_ENTRY_UUID, APR_HASH_KEY_STRING, str);
+    }
 
   return SVN_NO_ERROR;
 }
@@ -2884,6 +2890,59 @@ get_deleted_rev(svn_ra_svn_conn_t *conn,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+get_inherited_props(svn_ra_svn_conn_t *conn,
+                    apr_pool_t *pool,
+                    apr_array_header_t *params,
+                    void *baton)
+{
+  server_baton_t *b = baton;
+  const char *path, *full_path;
+  svn_revnum_t rev;
+  svn_fs_root_t *root;
+  apr_array_header_t *inherited_props;
+  int i;
+
+  /* Parse arguments. */
+  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)", &path, &rev));
+
+  full_path = svn_fspath__join(b->fs_path->data,
+                               svn_relpath_canonicalize(path, pool), pool);
+
+  /* Check authorizations */
+  SVN_ERR(must_have_access(conn, pool, b, svn_authz_read,
+                           full_path, FALSE));
+
+  if (!SVN_IS_VALID_REVNUM(rev))
+    SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool));
+
+  SVN_ERR(log_command(b, conn, pool, "%s",
+                      svn_log__get_inherited_props(full_path, rev, pool)));
+
+  /* Fetch the properties and a stream for the contents. */
+  SVN_CMD_ERR(svn_fs_revision_root(&root, b->fs, rev, pool));
+  SVN_CMD_ERR(get_props(NULL, &inherited_props, root, full_path, pool));
+
+  /* Send successful command response with revision and props. */
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(!", "success"));
+
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!(?!"));
+  for (i = 0; i < inherited_props->nelts; i++)
+    {
+      svn_prop_inherited_item_t *iprop =
+        APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
+
+      SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!(c(!",
+                                     iprop->path_or_url));
+      SVN_ERR(svn_ra_svn_write_proplist(conn, pool, iprop->prop_hash));
+      SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))!",
+                                     iprop->path_or_url));
+    }  
+
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+  return SVN_NO_ERROR;
+}
+
 static const svn_ra_svn_cmd_entry_t main_commands[] = {
   { "reparent",        reparent },
   { "get-latest-rev",  get_latest_rev },
@@ -2915,6 +2974,7 @@ static const svn_ra_svn_cmd_entry_t main
   { "replay",          replay },
   { "replay-range",    replay_range },
   { "get-deleted-rev", get_deleted_rev },
+  { "get-iprops",      get_inherited_props },
   { NULL }
 };
 



Mime
View raw message