You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by pb...@apache.org on 2012/03/27 00:29:55 UTC

svn commit: r1305641 - in /subversion/branches/inheritable-props/subversion: libsvn_ra_svn/client.c libsvn_ra_svn/protocol svnserve/serve.c

Author: pburba
Date: Mon Mar 26 22:29:55 2012
New Revision: 1305641

URL: http://svn.apache.org/viewvc?rev=1305641&view=rev
Log:
On the inheritable-props branch: Implement getting inherited props over
ra_svn.

* subversion/libsvn_client/prop_commands.c
  (remote_proplist): Raise an error if we insist on asking a server for
   inherited props if that server isn't advertising the
   SVN_RA_CAPABILITY_INHERITED_PROPS capability.

* subversion/libsvn_ra_svn/client.c
  (parse_iproplist): New.

  (ra_svn_get_file,
   ra_svn_get_dir): Implement the client-side stuffs for getting inherited
   props over ra_svn.

* subversion/libsvn_ra_svn/protocol
  (get-file,
   get-dir): Document the new protocol options.

* subversion/svnserve/serve.c
  (get_props): Support getting inherited props via svn_fs_node_proplist2.

  (get_file,
   get_dir): Implement the server-side stuffs for getting inherited props
   over ra_svn.

Modified:
    subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c
    subversion/branches/inheritable-props/subversion/libsvn_ra_svn/protocol
    subversion/branches/inheritable-props/subversion/svnserve/serve.c

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=1305641&r1=1305640&r2=1305641&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_svn/client.c Mon Mar 26 22:29:55 2012
@@ -1009,6 +1009,82 @@ static svn_error_t *ra_svn_commit(svn_ra
   return SVN_NO_ERROR;
 }
 
+/* Parse IPROPLIST, an array of svn_ra_svn_item_t structures, as a list of
+   const char * repos relative paths and properties for those paths, storing
+   the result as an array of svn_prop_inherited_item_t *items. */
+static svn_error_t *
+parse_iproplist(apr_array_header_t **inherited_props,
+                const apr_array_header_t *iproplist,
+                svn_ra_session_t *session,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+
+{
+  int i;
+  const char *repos_root_url;
+  apr_pool_t *iterpool;
+
+  if (iproplist == NULL)
+    {
+      /* If the server doesn't have the SVN_RA_CAPABILITY_INHERITED_PROPS
+         capability we shouldn't be asking for inherited props, but if we
+         did and the server sent back nothing then we'll want to handle
+         that. */
+      *inherited_props = NULL;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, scratch_pool));
+
+  *inherited_props = apr_array_make(
+    result_pool, iproplist->nelts, sizeof(svn_prop_inherited_item_t *));
+
+  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--)
+    {
+      apr_array_header_t *iprop_list;
+      char *parent_rel_path;
+      apr_hash_t *iprops;
+      apr_hash_index_t *hi;
+      svn_prop_inherited_item_t *new_iprop =
+        apr_palloc(result_pool, sizeof(*new_iprop));
+      svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(iproplist, i,
+                                              svn_ra_svn_item_t);
+      if (elt->kind != SVN_RA_SVN_LIST)
+        return svn_error_create(
+          SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+          _("Inherited proplist element not a list"));
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, iterpool, "cl",
+                                     &parent_rel_path, &iprop_list));
+      SVN_ERR(svn_ra_svn_parse_proplist(iprop_list, iterpool, &iprops));
+      new_iprop->path_or_url = svn_path_url_add_component2(repos_root_url,
+                                                           parent_rel_path,
+                                                           result_pool);
+      new_iprop->prop_hash = apr_hash_make(result_pool);
+      for (hi = apr_hash_first(iterpool, iprops);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          const char *name = svn__apr_hash_index_key(hi);
+          svn_string_t *value = svn__apr_hash_index_val(hi);
+          apr_hash_set(new_iprop->prop_hash,
+                       apr_pstrdup(result_pool, name),
+                       APR_HASH_KEY_STRING,
+                       svn_string_dup(value, result_pool));
+        }
+      APR_ARRAY_PUSH(*inherited_props, svn_prop_inherited_item_t *) =
+        new_iprop;
+    }
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path,
                                     svn_revnum_t rev, svn_stream_t *stream,
                                     svn_revnum_t *fetched_rev,
@@ -1019,22 +1095,26 @@ static svn_error_t *ra_svn_get_file(svn_
   svn_ra_svn__session_baton_t *sess_baton = session->priv;
   svn_ra_svn_conn_t *conn = sess_baton->conn;
   apr_array_header_t *proplist;
+  apr_array_header_t *iproplist;
   const char *expected_digest;
   svn_checksum_t *expected_checksum = NULL;
   svn_checksum_ctx_t *checksum_ctx;
   apr_pool_t *iterpool;
 
-  SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-file", "c(?r)bb", path,
-                               rev, (props != NULL), (stream != NULL)));
+  SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "get-file", "c(?r)bbb", path,
+                               rev, (props != NULL), (stream != NULL),
+                               (inherited_props != NULL)));
   SVN_ERR(handle_auth_request(sess_baton, pool));
-  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "(?c)rl",
+  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "(?c)rl?l",
                                        &expected_digest,
-                                       &rev, &proplist));
+                                       &rev, &proplist, &iproplist));
 
   if (fetched_rev)
     *fetched_rev = rev;
   if (props)
     SVN_ERR(svn_ra_svn_parse_proplist(proplist, pool, props));
+  if (inherited_props)
+    SVN_ERR(parse_iproplist(inherited_props, iproplist, session, pool, pool));
 
   /* We're done if the contents weren't wanted. */
   if (!stream)
@@ -1098,7 +1178,7 @@ static svn_error_t *ra_svn_get_dir(svn_r
 {
   svn_ra_svn__session_baton_t *sess_baton = session->priv;
   svn_ra_svn_conn_t *conn = sess_baton->conn;
-  apr_array_header_t *proplist, *dirlist;
+  apr_array_header_t *proplist, *dirlist, *iproplist;
   int i;
 
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(c(?r)bb(!", "get-dir", path,
@@ -1116,16 +1196,20 @@ static svn_error_t *ra_svn_get_dir(svn_r
   if (dirent_fields & SVN_DIRENT_LAST_AUTHOR)
     SVN_ERR(svn_ra_svn_write_word(conn, pool, SVN_RA_SVN_DIRENT_LAST_AUTHOR));
 
-  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!))"));
+  SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)b)",
+                                 (inherited_props != NULL)));
 
   SVN_ERR(handle_auth_request(sess_baton, pool));
-  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "rll", &rev, &proplist,
-                                       &dirlist));
+  SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "rll?l", &rev, &proplist,
+                                       &dirlist, &iproplist));
 
   if (fetched_rev)
     *fetched_rev = rev;
   if (props)
     SVN_ERR(svn_ra_svn_parse_proplist(proplist, pool, props));
+  if (inherited_props)
+    SVN_ERR(parse_iproplist(inherited_props, iproplist, session, pool,
+                            pool));
 
   /* We're done if dirents aren't wanted. */
   if (!dirents)

Modified: subversion/branches/inheritable-props/subversion/libsvn_ra_svn/protocol
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/libsvn_ra_svn/protocol?rev=1305641&r1=1305640&r2=1305641&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/libsvn_ra_svn/protocol (original)
+++ subversion/branches/inheritable-props/subversion/libsvn_ra_svn/protocol Mon Mar 26 22:29:55 2012
@@ -222,6 +222,7 @@ responds.
 Here are some miscellaneous prototypes used by the command sets:
 
   proplist:  ( ( name:string value:string ) ... )
+  iproplist: ( ( name:string proplist ) ... )
   propdelta: ( ( name:string [ value:string ] ) ... )
   node-kind: none|file|dir|unknown
   bool:      true|false
@@ -293,8 +294,10 @@ second place for auth-request point as n
                    ? ( post-commit-err:string ) )
 
   get-file
-    params:   ( path:string [ rev:number ] want-props:bool want-contents:bool )
-    response: ( [ checksum:string ] rev:number props:proplist )
+    params:   ( path:string [ rev:number ] want-props:bool want-contents:bool
+                [ want-iprops:bool ] )
+    response: ( [ checksum:string ] rev:number props:proplist
+                [ inherited-props:iproplist ] )
     If want-contents is specified, then after sending response, server
      sends file contents as a series of strings, terminated by the empty
      string, followed by a second empty command response to indicate
@@ -302,8 +305,9 @@ second place for auth-request point as n
 
   get-dir
     params:   ( path:string [ rev:number ] want-props:bool want-contents:bool
-                ? ( field:dirent-field ... ) )
-    response: ( rev:number props:proplist ( entry:dirent ... ) )]
+                ? ( field:dirent-field ... ) [ want-iprops:bool ] )
+    response: ( rev:number props:proplist ( entry:dirent ... )
+                [ inherited-props:iproplist ] )]
     dirent:   ( name:string kind:node-kind size:number has-props:bool
                 created-rev:number [ created-date:string ]
                 [ last-author:string ] )

Modified: subversion/branches/inheritable-props/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/inheritable-props/subversion/svnserve/serve.c?rev=1305641&r1=1305640&r2=1305641&view=diff
==============================================================================
--- subversion/branches/inheritable-props/subversion/svnserve/serve.c (original)
+++ subversion/branches/inheritable-props/subversion/svnserve/serve.c Mon Mar 26 22:29:55 2012
@@ -963,15 +963,19 @@ 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. */
-static svn_error_t *get_props(apr_hash_t **props, svn_fs_root_t *root,
-                              const char *path, apr_pool_t *pool)
+static svn_error_t *
+get_props(apr_hash_t **props,
+          apr_array_header_t **iprops,
+          svn_fs_root_t *root,
+          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_proplist(props, root, path, pool));
+  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,
@@ -1390,16 +1394,20 @@ static svn_error_t *get_file(svn_ra_svn_
   svn_fs_root_t *root;
   svn_stream_t *contents;
   apr_hash_t *props = NULL;
+  apr_array_header_t *inherited_props;
   svn_string_t write_str;
   char buf[4096];
   apr_size_t len;
   svn_boolean_t want_props, want_contents;
+  apr_uint64_t wants_inherited_props;
   svn_checksum_t *checksum;
   svn_error_t *err, *write_err;
+  int i;
 
   /* Parse arguments. */
-  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)bb", &path, &rev,
-                                 &want_props, &want_contents));
+  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)bb?B", &path, &rev,
+                                 &want_props, &want_contents,
+                                 &wants_inherited_props));
 
   full_path = svn_fspath__join(b->fs_path->data,
                                svn_relpath_canonicalize(path, pool), pool);
@@ -1420,8 +1428,8 @@ static svn_error_t *get_file(svn_ra_svn_
   SVN_CMD_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, root,
                                    full_path, TRUE, pool));
   hex_digest = svn_checksum_to_cstring_display(checksum, pool);
-  if (want_props)
-    SVN_CMD_ERR(get_props(&props, root, full_path, pool));
+  if (want_props || wants_inherited_props)
+    SVN_CMD_ERR(get_props(&props, &inherited_props, root, full_path, pool));
   if (want_contents)
     SVN_CMD_ERR(svn_fs_file_contents(&contents, root, full_path, pool));
 
@@ -1429,6 +1437,23 @@ static svn_error_t *get_file(svn_ra_svn_
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w((?c)r(!", "success",
                                  hex_digest, rev));
   SVN_ERR(svn_ra_svn_write_proplist(conn, pool, props));
+
+  if (wants_inherited_props)
+    {
+      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, "!))"));
 
   /* Now send the file's contents. */
@@ -1473,17 +1498,21 @@ static svn_error_t *get_dir(svn_ra_svn_c
   const char *path, *full_path, *file_path, *cdate;
   svn_revnum_t rev;
   apr_hash_t *entries, *props = NULL, *file_props;
+  apr_array_header_t *inherited_props;
   apr_hash_index_t *hi;
   svn_fs_root_t *root;
   apr_pool_t *subpool;
   svn_boolean_t want_props, want_contents;
+  apr_uint64_t wants_inherited_props;
   apr_uint64_t dirent_fields;
   apr_array_header_t *dirent_fields_list = NULL;
   svn_ra_svn_item_t *elt;
+  int i;
 
-  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)bb?l", &path, &rev,
+  SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)bb?l?B", &path, &rev,
                                  &want_props, &want_contents,
-                                 &dirent_fields_list));
+                                 &dirent_fields_list,
+                                 &wants_inherited_props));
 
   if (! dirent_fields_list)
     {
@@ -1491,8 +1520,6 @@ static svn_error_t *get_dir(svn_ra_svn_c
     }
   else
     {
-      int i;
-
       dirent_fields = 0;
 
       for (i = 0; i < dirent_fields_list->nelts; ++i)
@@ -1536,9 +1563,10 @@ static svn_error_t *get_dir(svn_ra_svn_c
   /* Fetch the root of the appropriate revision. */
   SVN_CMD_ERR(svn_fs_revision_root(&root, b->fs, rev, pool));
 
-  /* Fetch the directory properties if requested. */
-  if (want_props)
-    SVN_CMD_ERR(get_props(&props, root, full_path, pool));
+  /* Fetch the directory's explicit and/or inherited properties
+     if requested. */
+  if (want_props || wants_inherited_props)
+    SVN_CMD_ERR(get_props(&props, &inherited_props, root, full_path, pool));
 
   /* Begin response ... */
   SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(r(!", "success", rev));
@@ -1612,6 +1640,22 @@ static svn_error_t *get_dir(svn_ra_svn_c
       svn_pool_destroy(subpool);
     }
 
+  if (wants_inherited_props)
+    {
+      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));
+        }  
+    }
+
   /* Finish response. */
   return svn_ra_svn_write_tuple(conn, pool, "!))");
 }



Re: svn commit: r1305641 - in /subversion/branches/inheritable-props/subversion: libsvn_ra_svn/client.c libsvn_ra_svn/protocol svnserve/serve.c

Posted by Daniel Shahaf <da...@elego.de>.
pburba@apache.org wrote on Mon, Mar 26, 2012 at 22:29:55 -0000:
> Author: pburba
> Date: Mon Mar 26 22:29:55 2012
> New Revision: 1305641
> 
> URL: http://svn.apache.org/viewvc?rev=1305641&view=rev
> Log:
> On the inheritable-props branch: Implement getting inherited props over
> ra_svn.
> 
> * subversion/libsvn_ra_svn/protocol
>   (get-file,
>    get-dir): Document the new protocol options.
> 

The protocol document doesn't mention the new capability (which an
earlier commit added).

> +++ subversion/branches/inheritable-props/subversion/svnserve/serve.c Mon Mar 26 22:29:55 2012
> +static svn_error_t *
> +get_props(apr_hash_t **props,
> +          apr_array_header_t **iprops,
> +          svn_fs_root_t *root,
> +          const char *path,
> +          apr_pool_t *pool)
>  {
>    /* Get the properties. */
> -  SVN_ERR(svn_fs_node_proplist(props, root, path, pool));
> +  SVN_ERR(svn_fs_node_proplist2(props, iprops, root, path, pool, pool));
>  

Don't you need an svn_repos_* wrapper here, where (eventually) authz
checks on the parents will be done?

Re: svn commit: r1305641 - in /subversion/branches/inheritable-props/subversion: libsvn_ra_svn/client.c libsvn_ra_svn/protocol svnserve/serve.c

Posted by Daniel Shahaf <da...@elego.de>.
pburba@apache.org wrote on Mon, Mar 26, 2012 at 22:29:55 -0000:
> Author: pburba
> Date: Mon Mar 26 22:29:55 2012
> New Revision: 1305641
> 
> URL: http://svn.apache.org/viewvc?rev=1305641&view=rev
> Log:
> On the inheritable-props branch: Implement getting inherited props over
> ra_svn.
> 
> * subversion/libsvn_ra_svn/protocol
>   (get-file,
>    get-dir): Document the new protocol options.
> 

The protocol document doesn't mention the new capability (which an
earlier commit added).

> +++ subversion/branches/inheritable-props/subversion/svnserve/serve.c Mon Mar 26 22:29:55 2012
> +static svn_error_t *
> +get_props(apr_hash_t **props,
> +          apr_array_header_t **iprops,
> +          svn_fs_root_t *root,
> +          const char *path,
> +          apr_pool_t *pool)
>  {
>    /* Get the properties. */
> -  SVN_ERR(svn_fs_node_proplist(props, root, path, pool));
> +  SVN_ERR(svn_fs_node_proplist2(props, iprops, root, path, pool, pool));
>  

Don't you need an svn_repos_* wrapper here, where (eventually) authz
checks on the parents will be done?