Author: julianfoad
Date: Fri Oct  7 16:57:09 2011
New Revision: 1180101

URL: http://svn.apache.org/viewvc?rev=1180101&view=rev
Log:
On the 'tree-read-api' branch: Initial API and implementation, untested.

* subversion/libsvn_client/tree.c,
  subversion/libsvn_client/tree.h:
    New files.

Added:
    subversion/branches/tree-read-api/subversion/libsvn_client/tree.c
    subversion/branches/tree-read-api/subversion/libsvn_client/tree.h

Added: subversion/branches/tree-read-api/subversion/libsvn_client/tree.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/tree.c?rev=1180101&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/tree.c (added)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/tree.c Fri Oct  
7 16:57:09 2011
@@ -0,0 +1,293 @@
+/*
+ * tree.c: reading a generic tree
+ *
+ * ====================================================================
+ *    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 "svn_dirent_uri.h"
+#include "client.h"
+#include "tree.h"
+
+
+/*-----------------------------------------------------------------*/
+
+
+/* */
+typedef struct disk_tree_baton_t
+{
+  const char *tree_abspath;
+} disk_tree_baton_t;
+
+/* */
+static svn_error_t *
+disk_tree_get_kind(svn_client_tree_t *tree,
+                   svn_node_kind_t *kind,
+                   const char *relpath,
+                   apr_pool_t *scratch_pool)
+{
+  disk_tree_baton_t *baton = tree->priv;
+  const char *abspath = svn_dirent_join(baton->tree_abspath, relpath,
+                                        scratch_pool);
+
+  SVN_ERR(svn_io_check_path(abspath, kind, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+disk_tree_get_file(svn_client_tree_t *tree,
+                   svn_stream_t **stream,
+                   apr_hash_t **props,
+                   const char *relpath,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
+{
+  disk_tree_baton_t *baton = tree->priv;
+  const char *abspath = svn_dirent_join(baton->tree_abspath, relpath,
+                                        scratch_pool);
+
+  if (stream)
+    SVN_ERR(svn_stream_open_readonly(stream, abspath,
+                                     result_pool, scratch_pool));
+  if (props)
+    *props = NULL;
+
+  return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+disk_tree_get_dir(svn_client_tree_t *tree,
+                  apr_hash_t **dirents,
+                  apr_hash_t **props,
+                  const char *relpath,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  disk_tree_baton_t *baton = tree->priv;
+  const char *abspath = svn_dirent_join(baton->tree_abspath, relpath,
+                                        scratch_pool);
+
+  if (dirents)
+    {
+      SVN_ERR(svn_io_get_dirents3(dirents, abspath, FALSE,
+                                  result_pool, scratch_pool));
+    }
+  if (props)
+    *props = NULL;
+
+  return SVN_NO_ERROR;
+}
+
+/* */
+static const svn_client_tree__vtable_t disk_tree_vtable =
+{
+  disk_tree_get_kind,
+  disk_tree_get_file,
+  disk_tree_get_dir
+};
+
+svn_error_t *
+svn_client__disk_tree(svn_client_tree_t **tree_p,
+                      const char *abspath,
+                      svn_delta_editor_t *editor,
+                      apr_pool_t *result_pool)
+{
+  svn_client_tree_t *tree = apr_palloc(result_pool, sizeof(*tree));
+  disk_tree_baton_t *baton = apr_palloc(result_pool, sizeof(*baton));
+
+  baton->tree_abspath = abspath;
+
+  tree->vtable = &disk_tree_vtable;
+  tree->pool = result_pool;
+  tree->priv = baton;
+
+  *tree_p = tree;
+  return SVN_NO_ERROR;
+}
+
+/*-----------------------------------------------------------------*/
+
+
+svn_error_t *
+svn_client__wc_base_tree(svn_client_tree_t **tree_p,
+                         const char *path,
+                         svn_delta_editor_t *editor,
+                         apr_pool_t *result_pool)
+{
+  svn_client_tree_t *tree = apr_pcalloc(result_pool, sizeof(*tree));
+
+  *tree_p = tree;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__wc_working_tree(svn_client_tree_t **tree_p,
+                            const char *path,
+                            svn_delta_editor_t *editor,
+                            apr_pool_t *result_pool)
+{
+  svn_client_tree_t *tree = apr_pcalloc(result_pool, sizeof(*tree));
+
+  *tree_p = tree;
+  return SVN_NO_ERROR;
+}
+
+/*-----------------------------------------------------------------*/
+
+
+/* */
+typedef struct ra_tree_baton_t
+{
+  svn_ra_session_t *ra_session;
+  svn_revnum_t revnum;
+} ra_tree_baton_t;
+
+/* */
+static svn_error_t *
+ra_tree_get_kind(svn_client_tree_t *tree,
+                 svn_node_kind_t *kind,
+                 const char *relpath,
+                 apr_pool_t *scratch_pool)
+{
+  ra_tree_baton_t *baton = tree->priv;
+
+  SVN_ERR(svn_ra_check_path(baton->ra_session, relpath, baton->revnum,
+                            kind, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+ra_tree_get_file(svn_client_tree_t *tree,
+                 svn_stream_t **stream,
+                 apr_hash_t **props,
+                 const char *relpath,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  ra_tree_baton_t *baton = tree->priv;
+  svn_stream_t *holding_stream;
+  
+  SVN_ERR(svn_stream_open_unique(&holding_stream, NULL, NULL,
+                                 svn_io_file_del_on_close,
+                                 scratch_pool, scratch_pool));
+  SVN_ERR(svn_ra_get_file(baton->ra_session, relpath, baton->revnum,
+                          holding_stream, NULL, props, result_pool));
+  SVN_ERR(svn_stream_reset(holding_stream));
+  *stream = holding_stream;
+  return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+ra_tree_get_dir(svn_client_tree_t *tree,
+                apr_hash_t **dirents,
+                apr_hash_t **props,
+                const char *relpath,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  ra_tree_baton_t *baton = tree->priv;
+  apr_hash_t *ra_dirents = NULL;
+
+  SVN_ERR(svn_ra_get_dir2(baton->ra_session,
+                          dirents ? &ra_dirents : NULL, NULL, props,
+                          relpath, baton->revnum,
+                          SVN_DIRENT_KIND | SVN_DIRENT_SIZE,
+                          result_pool));
+  if (ra_dirents)
+    {
+      apr_hash_index_t *hi;
+
+      *dirents = apr_hash_make(result_pool);
+      for (hi = apr_hash_first(scratch_pool, ra_dirents);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          const char *entry_name = svn__apr_hash_index_key(hi);
+          svn_dirent_t *ra_dirent = svn__apr_hash_index_val(hi);
+          svn_client_tree_dirent_t *dirent
+            = apr_palloc(result_pool, sizeof(*dirent));
+
+          dirent->kind = ra_dirent->kind;
+          dirent->filesize = ra_dirent->size;
+          /* ### dirent->special = ... */
+          apr_hash_set(*dirents, entry_name, APR_HASH_KEY_STRING, dirent);
+        }
+    }
+  return SVN_NO_ERROR;
+}
+
+/* */
+static const svn_client_tree__vtable_t ra_tree_vtable =
+{
+  ra_tree_get_kind,
+  ra_tree_get_file,
+  ra_tree_get_dir
+};
+
+/* */
+static svn_error_t *
+read_ra_tree(svn_client_tree_t **tree_p,
+             svn_ra_session_t *ra_session,
+             svn_revnum_t revnum,
+             svn_client_ctx_t *ctx,
+             apr_pool_t *result_pool)
+{
+  svn_client_tree_t *tree = apr_pcalloc(result_pool, sizeof(*tree));
+  ra_tree_baton_t *baton = apr_palloc(result_pool, sizeof(*baton));
+
+  baton->ra_session = ra_session;
+  baton->revnum = revnum;
+
+  tree->vtable = &ra_tree_vtable;
+  tree->pool = result_pool;
+  tree->priv = baton;
+
+  *tree_p = tree;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__repository_tree(svn_client_tree_t **tree_p,
+                            const char *path_or_url,
+                            const svn_opt_revision_t *peg_revision,
+                            const svn_opt_revision_t *revision,
+                            svn_client_ctx_t *ctx,
+                            apr_pool_t *result_pool)
+{
+  svn_ra_session_t *ra_session;
+  svn_revnum_t revnum;
+  const char *url;
+
+  /* Get the RA connection. */
+  SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
+                                           &url, path_or_url, NULL,
+                                           peg_revision, revision,
+                                           ctx, result_pool));
+
+  SVN_ERR(read_ra_tree(tree_p, ra_session, revnum,
+                       ctx, result_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/*-----------------------------------------------------------------*/

Added: subversion/branches/tree-read-api/subversion/libsvn_client/tree.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_client/tree.h?rev=1180101&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_client/tree.h (added)
+++ subversion/branches/tree-read-api/subversion/libsvn_client/tree.h Fri Oct  
7 16:57:09 2011
@@ -0,0 +1,164 @@
+/* 
+ * File:   tree.h
+ * Author: julianfoad
+ *
+ * Created on 07 October 2011, 17:39
+ */
+
+#ifndef TREE_H
+#define        TREE_H
+
+#include <apr_hash.h>
+#include "svn_types.h"
+#include "svn_io.h"
+#include "svn_delta.h"
+#include "svn_opt.h"
+#include "svn_client.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Present as a tree:
+ *   an unversioned disk tree;
+ *   a WC base tree
+ *   a WC working tree
+ *   a repository tree
+ * 
+ * The consumer "pulls" parts of the tree and can omit unwanted parts.
+ * Consumer can pull any subtree "recursively" for efficient streaming.
+ */
+
+/**
+ * A readable tree.  This object is used to perform read requests to a
+ * repository tree or a working-copy (base or working) tree or any other
+ * readable tree.
+ *
+ * @since New in 1.8.
+ */
+typedef struct svn_client_tree_t svn_client_tree_t;
+
+/* */
+typedef svn_io_dirent2_t svn_client_tree_dirent_t;
+
+/* V-table for #svn_client_tree_t.
+ *
+ * Paths are relpaths, relative to the tree root.
+ * Revision numbers and repository ids are #SVN_INVALID_REVNUM and NULL
+ * for an unversioned node (including a node that is a local add/copy/move
+ * in a WC working tree).
+ */
+typedef struct svn_client_tree__vtable_t
+{
+  /* Fetch the node kind of the node at @a relpath.
+   * (### and other metadata? revnum? props?)
+   *
+   * Set @a *kind to the node kind.
+   */
+  svn_error_t *(*get_kind)(svn_client_tree_t *tree,
+                           svn_node_kind_t *kind,
+                           const char *relpath,
+                           apr_pool_t *scratch_pool);
+
+  /* Fetch the contents and properties of the file at @a relpath.
+   *
+   * If @a stream is non-NULL, set @a *stream to a readable stream yielding
+   * the contents of the file at @a relpath.  (### ? The stream
+   * handlers for @a stream may not perform any operations on @a tree.)
+   *
+   * If @a props is non-NULL, set @a *props to contain the regular
+   * versioned properties of the file (not 'wcprops', 'entryprops', etc.).
+   * The hash maps (const char *) names to (#svn_string_t *) values.
+   */
+  svn_error_t *(*get_file)(svn_client_tree_t *tree,
+                           svn_stream_t **stream,
+                           apr_hash_t **props,
+                           const char *relpath,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
+
+  /* Fetch the entries and properties of the directory at @a relpath.
+   *
+   * If @a dirents is non-NULL, set @a *dirents to contain all the entries
+   * of directory @a relpath.  The keys will be (<tt>const char *</tt>)
+   * entry names, and the values (#svn_client_tree_dirent_t *) dirents.
+   * Only the @c kind and @c filesize fields are filled in.
+   * ### @c special would be useful too.
+   *
+   * If @a props is non-NULL, set @a *props to contain the regular
+   * versioned properties of the file (not 'wcprops', 'entryprops', etc.).
+   * The hash maps (const char *) names to (#svn_string_t *) values.
+   */
+  svn_error_t *(*get_dir)(svn_client_tree_t *tree,
+                          apr_hash_t **dirents,
+                          apr_hash_t **props,
+                          const char *relpath,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool);
+
+  /* Push a sub-tree into an editor, as a delta against an empty tree.
+   * This is useful for efficiency when streaming a (sub-)tree from a
+   * remote source. */
+  svn_error_t *(*push_as_delta_edit)(svn_client_tree_t *tree,
+                                     const char *relpath,
+                                     svn_delta_editor_t *editor,
+                                     void *edit_baton,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool);
+} svn_client_tree__vtable_t;
+
+/* */
+struct svn_client_tree_t
+{
+  const svn_client_tree__vtable_t *vtable;
+
+  /* Pool used to manage this session. */
+  apr_pool_t *pool;
+
+  /* Private data for the tree implementation. */
+  void *priv;
+};
+
+
+/*-----------------------------------------------------------------*/
+
+
+/* */
+svn_error_t *
+svn_client__disk_tree(svn_client_tree_t **tree_p,
+                      const char *abspath,
+                      svn_delta_editor_t *editor,
+                      apr_pool_t *result_pool);
+
+/* */
+svn_error_t *
+svn_client__wc_base_tree(svn_client_tree_t **tree_p,
+                         const char *path,
+                         svn_delta_editor_t *editor,
+                         apr_pool_t *result_pool);
+
+/* */
+svn_error_t *
+svn_client__wc_working_tree(svn_client_tree_t **tree_p,
+                            const char *path,
+                            svn_delta_editor_t *editor,
+                            apr_pool_t *result_pool);
+
+/* */
+svn_error_t *
+svn_client__repository_tree(svn_client_tree_t **tree_p,
+                            const char *path_or_url,
+                            const svn_opt_revision_t *peg_revision,
+                            const svn_opt_revision_t *revision,
+                            svn_client_ctx_t *ctx,
+                            apr_pool_t *result_pool);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TREE_H */
+


Reply via email to