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 */
+