Author: stefan2
Date: Sat Nov 25 16:09:08 2017
New Revision: 1816313

URL: http://svn.apache.org/viewvc?rev=1816313&view=rev
Log:
Add the client-side implementation for the 'svn/list' report.

* subversion/libsvn_ra_serf/list.c
  (): New file implementing the client-side handling of the new report.

* subversion/libsvn_ra_serf/options.c
  (capabilities_headers_iterator_callback,
   options_response_handler): Use the new capability when advertized by
                              the server

* subversion/libsvn_ra_serf/ra_serf.h
  (svn_ra_serf__list): Declare new vtable function implementaton.

* subversion/libsvn_ra_serf/serf.c
  (serf_vtable): Enable the new report on the client-side.

Added:
    subversion/trunk/subversion/libsvn_ra_serf/list.c   (with props)
Modified:
    subversion/trunk/subversion/libsvn_ra_serf/options.c
    subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
    subversion/trunk/subversion/libsvn_ra_serf/serf.c

Added: subversion/trunk/subversion/libsvn_ra_serf/list.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/list.c?rev=1816313&view=auto
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/list.c (added)
+++ subversion/trunk/subversion/libsvn_ra_serf/list.c Sat Nov 25 16:09:08 2017
@@ -0,0 +1,299 @@
+/*
+ * list.c :  entry point for the list RA function in ra_serf
+ *
+ * ====================================================================
+ *    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_uri.h>
+#include <serf.h>
+
+#include "svn_hash.h"
+#include "svn_pools.h"
+#include "svn_ra.h"
+#include "svn_dav.h"
+#include "svn_base64.h"
+#include "svn_xml.h"
+#include "svn_config.h"
+#include "svn_path.h"
+#include "svn_props.h"
+#include "svn_time.h"
+
+#include "private/svn_dav_protocol.h"
+#include "private/svn_string_private.h"
+#include "private/svn_subr_private.h"
+#include "svn_private_config.h"
+
+#include "ra_serf.h"
+#include "../libsvn_ra/ra_loader.h"
+
+
+
+/*
+ * This enum represents the current state of our XML parsing for a REPORT.
+ */
+enum list_state_e {
+  INITIAL = XML_STATE_INITIAL,
+  REPORT,
+  ITEM,
+  AUTHOR
+};
+
+typedef struct list_context_t {
+  apr_pool_t *pool;
+
+  /* parameters set by our caller */
+  const char *path;
+  svn_revnum_t revision;
+  const apr_array_header_t *patterns;
+  svn_depth_t depth;
+  apr_uint32_t dirent_fields;
+  apr_array_header_t *props;
+
+  /* Buffer the author info for the current item.
+   * We use the AUTHOR pointer to differentiate between 0-length author
+   * strings and missing / NULL authors. */
+  const char *author;
+  svn_stringbuf_t *author_buf;
+
+  /* log receiver function and baton */
+  svn_ra_dirent_receiver_t receiver;
+  void *receiver_baton;
+} list_context_t;
+
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t log_ttable[] = {
+  { INITIAL, S_, "list-report", REPORT,
+    FALSE, { NULL }, FALSE },
+
+  { REPORT, S_, "item", ITEM,
+    TRUE, { "node-kind", "?size", "?has-props", "?created-rev",
+             "?date", NULL }, TRUE },
+
+  { ITEM, D_, "creator-displayname", AUTHOR,
+    TRUE, { "?encoding", NULL }, TRUE },
+
+  { 0 }
+};
+
+/* Conforms to svn_ra_serf__xml_closed_t  */
+static svn_error_t *
+item_closed(svn_ra_serf__xml_estate_t *xes,
+            void *baton,
+            int leaving_state,
+            const svn_string_t *cdata,
+            apr_hash_t *attrs,
+            apr_pool_t *scratch_pool)
+{
+  list_context_t *list_ctx = baton;
+
+  if (leaving_state == AUTHOR)
+    {
+      /* For compatibility with liveprops, current servers will not use
+       * base64-encoding for "binary" user names bu simply drop the
+       * offending control chars.
+       *
+       * We might want to switch to revprop-style encoding, though,
+       * and this is the code to do that. */
+      const char *encoding = svn_hash_gets(attrs, "encoding");
+      if (encoding)
+        {
+          /* Check for a known encoding type.  This is easy -- there's
+             only one.  */
+          if (strcmp(encoding, "base64") != 0)
+            {
+              return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                                       _("Unsupported encoding '%s'"),
+                                       encoding);
+            }
+
+          cdata = svn_base64_decode_string(cdata, scratch_pool);
+        }
+
+      /* Remember until the next ITEM closing tag. */
+      svn_stringbuf_set(list_ctx->author_buf, cdata->data);
+      list_ctx->author = list_ctx->author_buf->data;
+    }
+  else if (leaving_state == ITEM)
+    {
+      const char *dirent_path = cdata->data;
+      const char *kind_word, *date, *crev, *size;
+      svn_dirent_t dirent = { 0 };
+
+      kind_word = svn_hash_gets(attrs, "node-kind");
+      size = svn_hash_gets(attrs, "size");
+
+      dirent.has_props = svn_hash__get_bool(attrs, "has-props", FALSE);
+      crev = svn_hash_gets(attrs, "created-rev");
+      date = svn_hash_gets(attrs, "date");
+
+      /* Convert data. */
+      dirent.kind = svn_node_kind_from_word(kind_word);
+
+      if (size)
+        SVN_ERR(svn_cstring_atoi64(&dirent.size, size));
+
+      if (crev)
+        SVN_ERR(svn_cstring_atoi64(&dirent.created_rev, crev));
+      else
+        dirent.created_rev = SVN_INVALID_REVNUM;
+
+      if (date)
+        SVN_ERR(svn_time_from_cstring(&dirent.time, date, scratch_pool));
+
+      if (list_ctx->author)
+        dirent.last_author = list_ctx->author;
+
+      /* Invoke RECEIVER */
+      SVN_ERR(list_ctx->receiver(dirent_path, &dirent,
+                                 list_ctx->receiver_baton, scratch_pool));
+
+      /* Reset buffered info. */
+      list_ctx->author = NULL;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Implements svn_ra_serf__request_body_delegate_t */
+static svn_error_t *
+create_list_body(serf_bucket_t **body_bkt,
+                 void *baton,
+                 serf_bucket_alloc_t *alloc,
+                 apr_pool_t *pool /* request pool */,
+                 apr_pool_t *scratch_pool)
+{
+  serf_bucket_t *buckets;
+  list_context_t *list_ctx = baton;
+  int i;
+
+  buckets = serf_bucket_aggregate_create(alloc);
+
+  svn_ra_serf__add_open_tag_buckets(buckets, alloc,
+                                    "S:list-report",
+                                    "xmlns:S", SVN_XML_NAMESPACE,
+                                    SVN_VA_NULL);
+
+  svn_ra_serf__add_tag_buckets(buckets,
+                               "S:path", list_ctx->path,
+                               alloc);
+  svn_ra_serf__add_tag_buckets(buckets,
+                               "S:revision",
+                               apr_ltoa(pool, list_ctx->revision),
+                               alloc);
+  svn_ra_serf__add_tag_buckets(buckets,
+                               "S:depth", svn_depth_to_word(list_ctx->depth),
+                               alloc);
+
+  if (list_ctx->patterns)
+    {
+      for (i = 0; i < list_ctx->patterns->nelts; i++)
+        {
+          char *name = APR_ARRAY_IDX(list_ctx->patterns, i, char *);
+          svn_ra_serf__add_tag_buckets(buckets,
+                                       "S:pattern", name,
+                                       alloc);
+        }
+      if (list_ctx->patterns->nelts == 0)
+        {
+          svn_ra_serf__add_empty_tag_buckets(buckets, alloc,
+                                             "S:no-patterns", SVN_VA_NULL);
+        }
+    }
+
+  for (i = 0; i < list_ctx->props->nelts; i++)
+    {
+      const svn_ra_serf__dav_props_t *prop
+        = &APR_ARRAY_IDX(list_ctx->props, i, const svn_ra_serf__dav_props_t);
+      const char *name
+        = apr_pstrcat(pool, prop->xmlns, prop->name, SVN_VA_NULL);
+
+      svn_ra_serf__add_tag_buckets(buckets, "S:prop", name, alloc);
+    }
+
+  svn_ra_serf__add_close_tag_buckets(buckets, alloc,
+                                     "S:list-report");
+
+  *body_bkt = buckets;
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_ra_serf__list(svn_ra_session_t *ra_session,
+                  const char *path,
+                  svn_revnum_t revision,
+                  const apr_array_header_t *patterns,
+                  svn_depth_t depth,
+                  apr_uint32_t dirent_fields,
+                  svn_ra_dirent_receiver_t receiver,
+                  void *receiver_baton,
+                  apr_pool_t *scratch_pool)
+{
+  list_context_t *list_ctx;
+  svn_ra_serf__session_t *session = ra_session->priv;
+  svn_ra_serf__handler_t *handler;
+  svn_ra_serf__xml_context_t *xmlctx;
+  const char *req_url;
+
+  list_ctx = apr_pcalloc(scratch_pool, sizeof(*list_ctx));
+  list_ctx->pool = scratch_pool;
+  list_ctx->receiver = receiver;
+  list_ctx->receiver_baton = receiver_baton;
+  list_ctx->path = path;
+  list_ctx->revision = revision;
+  list_ctx->patterns = patterns;
+  list_ctx->depth = depth;
+  list_ctx->dirent_fields = dirent_fields;
+  list_ctx->props = svn_ra_serf__get_dirent_props(dirent_fields, session,
+                                                  scratch_pool);
+  list_ctx->author_buf = svn_stringbuf_create_empty(scratch_pool);
+
+  /* At this point, we may have a deleted file.  So, we'll match ra_neon's
+   * behavior and use the larger of start or end as our 'peg' rev.
+   */
+  SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+                                      session,
+                                      NULL /* url */, revision,
+                                      scratch_pool, scratch_pool));
+
+  xmlctx = svn_ra_serf__xml_context_create(log_ttable,
+                                           NULL, item_closed, NULL,
+                                           list_ctx,
+                                           scratch_pool);
+  handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL,
+                                              scratch_pool);
+
+  handler->method = "REPORT";
+  handler->path = req_url;
+  handler->body_delegate = create_list_body;
+  handler->body_delegate_baton = list_ctx;
+  handler->body_type = "text/xml";
+
+  SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool));
+
+  if (handler->sline.code != 200)
+    SVN_ERR(svn_ra_serf__unexpected_status(handler));
+
+  return SVN_NO_ERROR;
+}

Propchange: subversion/trunk/subversion/libsvn_ra_serf/list.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=1816313&r1=1816312&r2=1816313&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/options.c Sat Nov 25 16:09:08 
2017
@@ -232,6 +232,11 @@ capabilities_headers_iterator_callback(v
              advertise this capability (Subversion 1.10 and greater). */
           session->supports_svndiff1 = TRUE;
         }
+      if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LIST, vals))
+        {
+          svn_hash_sets(session->capabilities,
+                        SVN_RA_CAPABILITY_LIST, capability_yes);
+        }
       if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF2, vals))
         {
           /* Same for svndiff2. */
@@ -384,6 +389,8 @@ options_response_handler(serf_request_t
                     capability_no);
       svn_hash_sets(session->capabilities, 
SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
                     capability_no);
+      svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_LIST,
+                    capability_no);
 
       /* Then see which ones we can discover. */
       serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,

Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1816313&r1=1816312&r2=1816313&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Sat Nov 25 16:09:08 
2017
@@ -1431,6 +1431,18 @@ svn_ra_serf__get_locks(svn_ra_session_t
                        svn_depth_t depth,
                        apr_pool_t *pool);
 
+/* Implements svn_ra__vtable_t.list(). */
+svn_error_t *
+svn_ra_serf__list(svn_ra_session_t *ra_session,
+                  const char *path,
+                  svn_revnum_t revision,
+                  const apr_array_header_t *patterns,
+                  svn_depth_t depth,
+                  apr_uint32_t dirent_fields,
+                  svn_ra_dirent_receiver_t receiver,
+                  void *receiver_baton,
+                  apr_pool_t *scratch_pool);
+
 /* Request a mergeinfo-report from the URL attached to SESSION,
    and fill in the MERGEINFO hash with the results.
 

Modified: subversion/trunk/subversion/libsvn_ra_serf/serf.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/serf.c?rev=1816313&r1=1816312&r2=1816313&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/serf.c Sat Nov 25 16:09:08 2017
@@ -1063,7 +1063,7 @@ static const svn_ra__vtable_t serf_vtabl
   svn_ra_serf__get_deleted_rev,
   svn_ra_serf__get_inherited_props,
   NULL /* set_svn_ra_open */,
-  NULL /* svn_ra_list */,
+  svn_ra_serf__list,
   svn_ra_serf__register_editor_shim_callbacks,
   NULL /* commit_ev2 */,
   NULL /* replay_range_ev2 */


Reply via email to