You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/11/07 17:33:29 UTC
svn commit: r1406709 - in /subversion/branches/tree-read-api/subversion:
include/ include/private/ libsvn_ra/ libsvn_subr/ libsvn_wc/
Author: julianfoad
Date: Wed Nov 7 16:33:29 2012
New Revision: 1406709
URL: http://svn.apache.org/viewvc?rev=1406709&view=rev
Log:
On the 'tree-read-api' branch: Add an initial version of the tree API.
* subversion/include/svn_types.h
(svn_tree_t, svn_tree_node_t): New types.
* subversion/include/svn_tree.h
New file, with the public functions operating on trees and tree nodes.
* subversion/include/private/svn_tree_impl.h
New file, with the declarations needed by tree implementors.
* subversion/include/private/svn_ra_private.h
(svn_ra__open_tree): New functions.
* subversion/include/private/svn_subr_private.h
(svn_io__open_tree): New functions.
* subversion/include/private/svn_wc_private.h
(svn_wc__open_base_tree, svn_wc__open_pristine_tree,
svn_wc__open_actual_tree): New functions.
* subversion/libsvn_ra/ra_trees.c,
subversion/libsvn_subr/disk_trees.c,
subversion/libsvn_wc/wc_trees.c
New files, implementing different types of tree.
* subversion/libsvn_subr/tree.c
New file, implementing the generic tree functions.
Added:
subversion/branches/tree-read-api/subversion/include/private/svn_tree_impl.h (with props)
subversion/branches/tree-read-api/subversion/include/svn_tree.h (with props)
subversion/branches/tree-read-api/subversion/libsvn_ra/ra_trees.c (with props)
subversion/branches/tree-read-api/subversion/libsvn_subr/disk_trees.c (with props)
subversion/branches/tree-read-api/subversion/libsvn_subr/tree.c (with props)
subversion/branches/tree-read-api/subversion/libsvn_wc/wc_trees.c (with props)
Modified:
subversion/branches/tree-read-api/subversion/include/private/svn_ra_private.h
subversion/branches/tree-read-api/subversion/include/private/svn_subr_private.h
subversion/branches/tree-read-api/subversion/include/private/svn_wc_private.h
subversion/branches/tree-read-api/subversion/include/svn_types.h
Modified: subversion/branches/tree-read-api/subversion/include/private/svn_ra_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/include/private/svn_ra_private.h?rev=1406709&r1=1406708&r2=1406709&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/include/private/svn_ra_private.h (original)
+++ subversion/branches/tree-read-api/subversion/include/private/svn_ra_private.h Wed Nov 7 16:33:29 2012
@@ -272,6 +272,15 @@ svn_ra__replay_ev2(svn_ra_session_t *ses
svn_editor_t *editor,
apr_pool_t *scratch_pool);
+/* Set *TREE_P to a new tree object representing the subtree rooted at
+ * the repository path of SESSION in revision REVNUM.
+ */
+svn_error_t *
+svn_ra__open_tree(svn_tree_t **tree_p,
+ svn_ra_session_t *ra_session,
+ svn_revnum_t revnum,
+ apr_pool_t *result_pool);
+
#ifdef __cplusplus
}
Modified: subversion/branches/tree-read-api/subversion/include/private/svn_subr_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/include/private/svn_subr_private.h?rev=1406709&r1=1406708&r2=1406709&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/include/private/svn_subr_private.h (original)
+++ subversion/branches/tree-read-api/subversion/include/private/svn_subr_private.h Wed Nov 7 16:33:29 2012
@@ -325,6 +325,17 @@ svn_version__at_least(svn_version_t *ver
/** @} */
+/* Set *TREE_P to a new tree object representing the subtree rooted at
+ * absolute path ABSPATH in the local file system.
+ *
+ * Each node in this tree has an empty set of properties.
+ */
+svn_error_t *
+svn_io__open_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ apr_pool_t *result_pool);
+
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Added: subversion/branches/tree-read-api/subversion/include/private/svn_tree_impl.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/include/private/svn_tree_impl.h?rev=1406709&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/include/private/svn_tree_impl.h (added)
+++ subversion/branches/tree-read-api/subversion/include/private/svn_tree_impl.h Wed Nov 7 16:33:29 2012
@@ -0,0 +1,126 @@
+/*
+ * svn_tree_impl.h: header for implementors of svn_tree_t
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ */
+
+#ifndef SVN_TREE_IMPL_H
+#define SVN_TREE_IMPL_H
+
+#include "svn_tree.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** V-table for #svn_tree_t. */
+typedef struct svn_tree__vtable_t
+{
+ /* See svn_tree_get_node_by_relpath(). */
+ svn_error_t *(*get_node_by_relpath)(svn_tree_node_t **node,
+ svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+} svn_tree__vtable_t;
+
+/** The implementation of the typedef #svn_tree_t. */
+struct svn_tree_t
+{
+ const svn_tree__vtable_t *vtable;
+
+ /* Private data for the implementation. */
+ void *priv;
+
+ /* Pool used to manage this session. ### What "session"? */
+ apr_pool_t *pool;
+};
+
+/** Create a new "tree" object with the given VTABLE and BATON.
+ *
+ * This is for use by an implementation of the tree class.
+ */
+svn_tree_t *
+svn_tree__create(const svn_tree__vtable_t *vtable,
+ void *baton,
+ apr_pool_t *result_pool);
+
+
+/* ---------------------------------------------------------------------- */
+
+/** V-table for #svn_tree_node_t. */
+typedef struct svn_tree_node__vtable_t
+{
+ /* See svn_tree_node_get_relpath(). */
+ svn_error_t *(*get_relpath)(svn_tree_node_t *node,
+ const char **relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+ /* See svn_tree_node_get_kind(). */
+ svn_error_t *(*get_kind)(svn_tree_node_t *node,
+ svn_node_kind_t *kind,
+ apr_pool_t *scratch_pool);
+
+ /* See svn_tree_node_get_file(). */
+ svn_error_t *(*get_file)(svn_tree_node_t *node,
+ svn_stream_t **stream,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+ /* See svn_tree_node_get_dir(). */
+ svn_error_t *(*read_dir)(svn_tree_node_t *node,
+ apr_hash_t **children,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+} svn_tree_node__vtable_t;
+
+/** The implementation of the typedef #svn_tree_t. */
+struct svn_tree_node_t
+{
+ const svn_tree_node__vtable_t *vtable;
+
+ /** Private data for the implementation. */
+ void *priv;
+
+ /** Pool for ### what purpose/lifetime? */
+ apr_pool_t *pool;
+};
+
+/** Create a new "tree node" object with the given VTABLE and BATON.
+ *
+ * This is for use by an implementation of the tree class.
+ */
+svn_tree_node_t *
+svn_tree_node_create(const svn_tree_node__vtable_t *vtable,
+ void *baton,
+ apr_pool_t *result_pool);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SVN_TREE_IMPL_H */
+
Propchange: subversion/branches/tree-read-api/subversion/include/private/svn_tree_impl.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/tree-read-api/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/include/private/svn_wc_private.h?rev=1406709&r1=1406708&r2=1406709&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/include/private/svn_wc_private.h (original)
+++ subversion/branches/tree-read-api/subversion/include/private/svn_wc_private.h Wed Nov 7 16:33:29 2012
@@ -1774,6 +1774,38 @@ svn_wc__move2(svn_wc_context_t *wc_ctx,
void *notify_baton,
apr_pool_t *scratch_pool);
+/* ---------------------------------------------------------------------- */
+
+/* Set *TREE_P to a new tree object representing the subtree rooted at
+ * absolute path ABSPATH in the 'base' layer of a working copy.
+ */
+svn_error_t *
+svn_wc__open_base_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool);
+
+/* Set *TREE_P to a new tree object representing the subtree rooted at
+ * absolute path ABSPATH in the 'pristine'/'working' layer of a working copy.
+*/
+svn_error_t *
+svn_wc__open_pristine_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool);
+
+/* Set *TREE_P to a new tree object representing the subtree rooted at
+ * absolute path ABSPATH in the 'actual' layer of a working copy.
+ *
+ * That is, the tree that would get exported by "svn export WC", or shown
+ * as the right-hand side of a diff in "svn diff WCPATH".
+ */
+svn_error_t *
+svn_wc__open_actual_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Added: subversion/branches/tree-read-api/subversion/include/svn_tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/include/svn_tree.h?rev=1406709&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/include/svn_tree.h (added)
+++ subversion/branches/tree-read-api/subversion/include/svn_tree.h Wed Nov 7 16:33:29 2012
@@ -0,0 +1,215 @@
+/*
+ * svn_tree.h: 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.
+ * ====================================================================
+ */
+
+#ifndef SVN_TREE_H
+#define SVN_TREE_H
+
+#include <apr_hash.h>
+#include "svn_types.h"
+#include "svn_io.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** Set @a *node_p to the root node of @a tree.
+ *
+ * Every tree has a root node, but it is possible that an error could be
+ * thrown for other reasons.
+ */
+svn_error_t *
+svn_tree_get_root_node(svn_tree_node_t **node_p,
+ svn_tree_t *tree,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/** Set @a *node_p to the node that has relative path @a relpath within @a tree.
+ *
+ * Return an error if not found.
+ */
+svn_error_t *
+svn_tree_get_node_by_relpath(svn_tree_node_t **node_p,
+ svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/** A tree-walker callback.
+ *
+ * This callback presents one tree node object being visited, @a node,
+ * and the closure @a walk_baton.
+ *
+ * ### TODO: Consider re-modelling, more like Python's OS tree walker
+ * that passes a list of subdirs and a list of non-dir children,
+ * and lets the list of subdirs be modified before it recurses into them.
+ *
+ * @a scratch_pool is available for use within the function until it returns.
+ */
+typedef svn_error_t *(*svn_tree_walk_func_t)(svn_tree_node_t *node,
+ void *walk_baton,
+ apr_pool_t *scratch_pool);
+
+/** Walk the generic tree @a tree.
+ *
+ * Traverse the tree depth-first, visiting the children in lexically sorted
+ * order within a directory. Recurse to depth @a depth. Do not recurse
+ * into any node for which there is no read authorization.
+ *
+ * Call @a walk_func for each visited node, passing @a walk_baton and the
+ * tree node object.
+ *
+ * If @a cancel_func is not null, call it with @a cancel_baton to check for
+ * cancellation.
+ */
+svn_error_t *
+svn_tree_walk(svn_tree_t *tree,
+ svn_depth_t depth,
+ svn_tree_walk_func_t walk_func,
+ void *walk_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/** A two-tree-walker callback.
+ *
+ * This callback presents two tree node objects being visited, @a node1
+ * and @a node2, and the closure @a walk_baton.
+ *
+ * ### TODO: Consider re-modelling, more like Python's OS tree walker
+ * that passes a list of subdirs and a list of non-dir children,
+ * and lets the list of subdirs be modified before it recurses into them.
+ *
+ * @a scratch_pool is available for use within the function until it returns.
+ */
+typedef svn_error_t *(*svn_tree_walk_two_func_t)(svn_tree_node_t *node1,
+ svn_tree_node_t *node2,
+ void *walk_baton,
+ apr_pool_t *scratch_pool);
+
+/** Walk the two generic trees @a tree1 and @a tree2, simultaneously,
+ * recursing to @a depth.
+ *
+ * Call @a walk_func for each node, passing @a walk_baton and the tree
+ * node object.
+ *
+ * If @a cancel_func is not null, call it with @a cancel_baton to check for
+ * cancellation.
+ *
+ * TODO: Visit nodes with the same id at the same time, thus tracking moves.
+ * TODO: Let the callback determine the order of walking sub-nodes,
+ * especially with respect to far-moves (moves into or out of a directory).
+ */
+svn_error_t *
+svn_tree_walk_two(svn_tree_t *tree1,
+ svn_tree_t *tree2,
+ svn_depth_t depth,
+ const svn_tree_walk_two_func_t walk_func,
+ void *walk_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/* ---------------------------------------------------------------------- */
+
+/** Set @a *relpath_p to the path of @a tree_node, relative to the root of
+ * the tree.
+ *
+ * If @a tree_node is not readable due to lack of authorization,
+ * return a #SVN_ERR_AUTHZ_UNREADABLE error.
+ */
+svn_error_t *
+svn_tree_node_get_relpath(svn_tree_node_t *node,
+ const char **relpath_p,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/** Set @a *kind to the node kind of @a tree_node.
+ *
+ * The kind will be 'file', 'dir', 'symlink' or 'none'; not 'unknown'.
+ *
+ * If @a tree_node is not readable due to lack of authorization,
+ * return a #SVN_ERR_AUTHZ_UNREADABLE error.
+ */
+svn_error_t *
+svn_tree_node_get_kind(svn_tree_node_t *node,
+ svn_node_kind_t *kind,
+ apr_pool_t *scratch_pool);
+
+/** Fetch the contents and/or properties of the file @a tree_node.
+ *
+ * If @a stream is non-NULL, set @a *stream to a readable stream yielding
+ * the contents of the file. (### ? The stream
+ * handlers for @a stream may not perform any operations on @a tree_node.)
+ *
+ * ###? If @a checksum is non-NULL, set @a *checksum to the SHA-1 checksum
+ * of the file content. The particular tree implementation must define
+ * whether checksum is guaranteed to be filled in by the time this function
+ * call returns or whether it is only guaranteed to happen by the time the
+ * caller has read all of the data from @a stream.
+ *
+ * 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.
+ *
+ * If @a tree_node is not readable due to lack of authorization,
+ * return a #SVN_ERR_AUTHZ_UNREADABLE error; otherwise, if it is the wrong
+ * kind of node, return a #SVN_ERR_WRONG_KIND error.
+ */
+svn_error_t *
+svn_tree_node_read_file(svn_tree_node_t *node,
+ svn_stream_t **stream,
+ /* svn_checksum_t **checksum, */
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/** Fetch the entries and/or properties of the directory @a tree_node.
+ *
+ * If @a dirents is non-NULL, set @a *dirents to contain all the entries
+ * of the directory @a tree_node. The hash maps (const char *) entry
+ * basenames to (svn_tree_node_t *) values.
+ *
+ * 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.
+ *
+ * If @a tree_node is not readable due to lack of authorization,
+ * return a #SVN_ERR_AUTHZ_UNREADABLE error; otherwise, if it is the wrong
+ * kind of node, return a #SVN_ERR_WRONG_KIND error.
+ */
+svn_error_t *
+svn_tree_node_read_dir(svn_tree_node_t *node,
+ apr_hash_t **dirents,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SVN_TREE_H */
+
Propchange: subversion/branches/tree-read-api/subversion/include/svn_tree.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/tree-read-api/subversion/include/svn_types.h
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/include/svn_types.h?rev=1406709&r1=1406708&r2=1406709&view=diff
==============================================================================
--- subversion/branches/tree-read-api/subversion/include/svn_types.h (original)
+++ subversion/branches/tree-read-api/subversion/include/svn_types.h Wed Nov 7 16:33:29 2012
@@ -1269,6 +1269,37 @@ typedef unsigned long svn_linenum_t;
+/** Abstract representation of a tree of #svn_tree_node_t.
+ *
+ * This object presents an interface for referring to, accessing and
+ * traversing a tree, usually a versioned tree, of the kind of nodes that
+ * Subversion versions.
+ *
+ * A tree always has a root node: a completely empty tree is not allowed.
+ *
+ * An implementation of this interface could represent, among other trees,
+ * * a tree in some revision of a repository,
+ * * the base or working version of a Working Copy tree,
+ * * an unversioned tree on disk (presumably without properties),
+ * * a temporary tree in memory, constructed on the fly.
+ *
+ * @since New in 1.x.
+ */
+typedef struct svn_tree_t svn_tree_t;
+
+/** Abstract representation of a tree node.
+ *
+ * Each node is a file, a directory or a symbolic link, and has a set of
+ * properties.
+ *
+ * @see #svn_tree_t
+ *
+ * @since New in 1.x.
+ */
+typedef struct svn_tree_node_t svn_tree_node_t;
+
+
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Added: subversion/branches/tree-read-api/subversion/libsvn_ra/ra_trees.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_ra/ra_trees.c?rev=1406709&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_ra/ra_trees.c (added)
+++ subversion/branches/tree-read-api/subversion/libsvn_ra/ra_trees.c Wed Nov 7 16:33:29 2012
@@ -0,0 +1,215 @@
+/*
+ * ra_trees.c: generic tree implementation of an in-repository subtree
+ *
+ * ====================================================================
+ * 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_types.h"
+#include "svn_pools.h"
+#include "svn_dirent_uri.h"
+#include "svn_tree.h"
+#include "svn_ra.h"
+
+#include "private/svn_tree_impl.h"
+#include "private/svn_ra_private.h"
+
+#include "svn_private_config.h"
+
+
+/* Wrap any RA-layer 'unauthorized read' error in an
+ * SVN_ERR_AUTHZ_UNREADABLE error. */
+static svn_error_t *
+ra_unauthz_err(svn_error_t *err)
+{
+ if (err && ((err->apr_err == SVN_ERR_RA_NOT_AUTHORIZED) ||
+ (err->apr_err == SVN_ERR_RA_DAV_FORBIDDEN)))
+ {
+ err = svn_error_createf(SVN_ERR_AUTHZ_UNREADABLE, err, NULL);
+ }
+ return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* */
+typedef struct ra_tree_baton_t
+{
+ svn_ra_session_t *ra_session;
+ svn_revnum_t revnum;
+} ra_tree_baton_t;
+
+/* */
+typedef struct ra_tree_node_baton_t
+{
+ svn_tree_t *tree;
+ ra_tree_baton_t *tb;
+ const char *relpath;
+} ra_tree_node_baton_t;
+
+/* Forward declaration */
+static svn_tree_node_t *
+ra_tree_node_create(svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool);
+
+/* */
+static svn_error_t *
+ra_tree_get_node_by_relpath(svn_tree_node_t **node,
+ svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *node = ra_tree_node_create(tree, relpath, result_pool);
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+ra_treen_get_relpath(svn_tree_node_t *node,
+ const char **relpath_p,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ ra_tree_node_baton_t *nb = node->priv;
+
+ *relpath_p = nb->relpath;
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+ra_treen_get_kind(svn_tree_node_t *node,
+ svn_node_kind_t *kind,
+ apr_pool_t *scratch_pool)
+{
+ ra_tree_node_baton_t *nb = node->priv;
+
+ SVN_ERR(ra_unauthz_err(svn_ra_check_path(nb->tb->ra_session, nb->relpath,
+ nb->tb->revnum, kind,
+ scratch_pool)));
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+ra_treen_read_file(svn_tree_node_t *node,
+ svn_stream_t **stream,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ ra_tree_node_baton_t *nb = node->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(ra_unauthz_err(svn_ra_get_file(nb->tb->ra_session, nb->relpath,
+ nb->tb->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_treen_read_dir(svn_tree_node_t *node,
+ apr_hash_t **children_p,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ ra_tree_node_baton_t *nb = node->priv;
+ apr_hash_t *dirents;
+
+ SVN_ERR(ra_unauthz_err(svn_ra_get_dir2(nb->tb->ra_session,
+ children_p ? &dirents : NULL,
+ NULL, props,
+ nb->relpath, nb->tb->revnum,
+ 0 /* dirent_fields */,
+ result_pool)));
+
+ /* Convert RA dirents to tree children */
+ if (children_p)
+ {
+ apr_hash_t *children = apr_hash_make(result_pool);
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, dirents); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ const char *relpath = svn_relpath_join(nb->relpath, name, result_pool);
+ svn_tree_node_t *child;
+
+ child = ra_tree_node_create(nb->tree, relpath, result_pool);
+ apr_hash_set(children, name, APR_HASH_KEY_STRING, child);
+ }
+ *children_p = children;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* */
+static const svn_tree__vtable_t ra_tree_vtable =
+{
+ ra_tree_get_node_by_relpath
+};
+
+/* */
+static const svn_tree_node__vtable_t ra_tree_node_vtable =
+{
+ ra_treen_get_relpath,
+ ra_treen_get_kind,
+ ra_treen_read_file,
+ ra_treen_read_dir
+};
+
+/* */
+static svn_tree_node_t *
+ra_tree_node_create(svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool)
+{
+ ra_tree_node_baton_t *nb = apr_palloc(result_pool, sizeof(*nb));
+
+ nb->tree = tree;
+ nb->tb = tree->priv;
+ nb->relpath = relpath;
+ return svn_tree_node_create(&ra_tree_node_vtable, nb, result_pool);
+}
+
+svn_error_t *
+svn_ra__open_tree(svn_tree_t **tree_p,
+ svn_ra_session_t *ra_session,
+ svn_revnum_t revnum,
+ apr_pool_t *result_pool)
+{
+ ra_tree_baton_t *tb = apr_palloc(result_pool, sizeof(*tb));
+
+ tb->ra_session = ra_session;
+ tb->revnum = revnum;
+
+ *tree_p = svn_tree__create(&ra_tree_vtable, tb, result_pool);
+ return SVN_NO_ERROR;
+}
Propchange: subversion/branches/tree-read-api/subversion/libsvn_ra/ra_trees.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: subversion/branches/tree-read-api/subversion/libsvn_subr/disk_trees.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_subr/disk_trees.c?rev=1406709&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_subr/disk_trees.c (added)
+++ subversion/branches/tree-read-api/subversion/libsvn_subr/disk_trees.c Wed Nov 7 16:33:29 2012
@@ -0,0 +1,202 @@
+/*
+ * disk_trees.c: generic tree implementation of unversioned disk trees
+ *
+ * ====================================================================
+ * 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_types.h"
+#include "svn_pools.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_tree.h"
+
+#include "private/svn_tree_impl.h"
+#include "private/svn_subr_private.h"
+
+#include "svn_private_config.h"
+
+
+/* */
+typedef struct disk_tree_baton_t
+{
+ const char *tree_abspath;
+} disk_tree_baton_t;
+
+/* */
+typedef struct disk_tree_node_baton_t
+{
+ svn_tree_t *tree;
+ disk_tree_baton_t *tb;
+ const char *relpath;
+} disk_tree_node_baton_t;
+
+/* Forward declaration */
+static svn_tree_node_t *
+disk_tree_node_create(svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool);
+
+/* */
+static svn_error_t *
+disk_tree_get_node_by_relpath(svn_tree_node_t **node,
+ svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *node = disk_tree_node_create(tree, relpath, result_pool);
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+disk_treen_get_relpath(svn_tree_node_t *node,
+ const char **relpath_p,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ disk_tree_node_baton_t *nb = node->priv;
+
+ *relpath_p = nb->relpath;
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+disk_treen_get_kind(svn_tree_node_t *node,
+ svn_node_kind_t *kind,
+ apr_pool_t *scratch_pool)
+{
+ disk_tree_node_baton_t *nb = node->priv;
+ const char *abspath = svn_dirent_join(nb->tb->tree_abspath,
+ nb->relpath, scratch_pool);
+
+ SVN_ERR(svn_io_check_path(abspath, kind, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+disk_treen_get_file(svn_tree_node_t *node,
+ svn_stream_t **stream,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ disk_tree_node_baton_t *nb = node->priv;
+ const char *abspath = svn_dirent_join(nb->tb->tree_abspath,
+ nb->relpath, scratch_pool);
+
+ if (stream)
+ SVN_ERR(svn_stream_open_readonly(stream, abspath,
+ result_pool, scratch_pool));
+ if (props)
+ *props = apr_hash_make(result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+/* Read a directory from disk.
+ * It's an unversioned tree on disk, so report no properties.
+ * TODO: Consider adding the ability to report svn:executable,
+ * auto-props, etc. like "svn add" does.
+ */
+static svn_error_t *
+disk_treen_get_dir(svn_tree_node_t *node,
+ apr_hash_t **children_p,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ disk_tree_node_baton_t *nb = node->priv;
+ const char *abspath = svn_dirent_join(nb->tb->tree_abspath,
+ nb->relpath, scratch_pool);
+
+ if (children_p)
+ {
+ apr_hash_t *dirents;
+ apr_hash_index_t *hi;
+ apr_hash_t *children = apr_hash_make(result_pool);
+
+ SVN_ERR(svn_io_get_dirents3(&dirents, abspath, FALSE,
+ result_pool, scratch_pool));
+
+ /* Convert RA dirents to tree children */
+ for (hi = apr_hash_first(scratch_pool, dirents); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ const char *relpath = svn_relpath_join(nb->relpath, name, result_pool);
+ svn_tree_node_t *child;
+
+ child = disk_tree_node_create(nb->tree, relpath, result_pool);
+ apr_hash_set(children, name, APR_HASH_KEY_STRING, child);
+ }
+ *children_p = children;
+ }
+
+ /* It's an unversioned tree on disk, so report no properties. */
+ if (props)
+ *props = apr_hash_make(result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+/* */
+static const svn_tree__vtable_t disk_tree_vtable =
+{
+ disk_tree_get_node_by_relpath
+};
+
+/* */
+static const svn_tree_node__vtable_t disk_tree_node_vtable =
+{
+ disk_treen_get_relpath,
+ disk_treen_get_kind,
+ disk_treen_get_file,
+ disk_treen_get_dir
+};
+
+/* */
+static svn_tree_node_t *
+disk_tree_node_create(svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool)
+{
+ disk_tree_node_baton_t *nb = apr_palloc(result_pool, sizeof(*nb));
+
+ nb->tree = tree;
+ nb->tb = tree->priv;
+ nb->relpath = relpath;
+ return svn_tree_node_create(&disk_tree_node_vtable, nb, result_pool);
+}
+
+svn_error_t *
+svn_io__open_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ apr_pool_t *result_pool)
+{
+ disk_tree_baton_t *tb = apr_palloc(result_pool, sizeof(*tb));
+
+ tb->tree_abspath = abspath;
+
+ *tree_p = svn_tree__create(&disk_tree_vtable, tb, result_pool);
+ return SVN_NO_ERROR;
+}
Propchange: subversion/branches/tree-read-api/subversion/libsvn_subr/disk_trees.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: subversion/branches/tree-read-api/subversion/libsvn_subr/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_subr/tree.c?rev=1406709&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_subr/tree.c (added)
+++ subversion/branches/tree-read-api/subversion/libsvn_subr/tree.c Wed Nov 7 16:33:29 2012
@@ -0,0 +1,344 @@
+/*
+ * 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 <assert.h>
+
+#include "svn_pools.h"
+#include "svn_sorts.h"
+#include "svn_dirent_uri.h"
+#include "svn_tree.h"
+
+#include "private/svn_tree_impl.h"
+
+#include "svn_private_config.h"
+
+
+svn_tree_t *
+svn_tree__create(const svn_tree__vtable_t *vtable,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ svn_tree_t *tree = apr_palloc(result_pool, sizeof(*tree));
+
+ tree->vtable = vtable;
+ tree->pool = result_pool;
+ tree->priv = baton;
+ return tree;
+}
+
+svn_error_t *
+svn_tree_get_root_node(svn_tree_node_t **node_p,
+ svn_tree_t *tree,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(tree->vtable->get_node_by_relpath(node_p, tree, "",
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_tree_get_node_by_relpath(svn_tree_node_t **node_p,
+ svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(tree->vtable->get_node_by_relpath(node_p, tree, relpath,
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+tree_node_get_kind_or_unknown(svn_node_kind_t *kind,
+ svn_tree_node_t *node,
+ apr_pool_t *scratch_pool)
+{
+ svn_error_t *err = svn_tree_node_get_kind(node, kind, scratch_pool);
+
+ if (err && err->apr_err == SVN_ERR_AUTHZ_UNREADABLE)
+ {
+ /* Can't read this node's kind. That's fine; pass 'unknown'. */
+ svn_error_clear(err);
+ *kind = svn_node_unknown;
+ return SVN_NO_ERROR;
+ }
+ return svn_error_trace(err);
+}
+
+/* The body of svn_tree_walk(), which see.
+ */
+static svn_error_t *
+walk_tree(svn_tree_node_t *node,
+ svn_depth_t depth,
+ svn_tree_walk_func_t walk_func,
+ void *walk_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_node_kind_t kind;
+
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
+ SVN_ERR(tree_node_get_kind_or_unknown(&kind, node, scratch_pool));
+
+ SVN_ERR(walk_func(node, walk_baton, scratch_pool));
+
+ /* Recurse */
+ if (kind == svn_node_dir && depth >= svn_depth_files)
+ {
+ apr_hash_t *dirents;
+ apr_array_header_t *dirents_sorted;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ int i;
+
+ SVN_ERR(svn_tree_node_read_dir(node, &dirents, NULL /* props */,
+ scratch_pool, scratch_pool));
+ dirents_sorted = svn_sort__hash(dirents,
+ svn_sort_compare_items_lexically,
+ scratch_pool);
+
+ for (i = 0; i < dirents_sorted->nelts; i++)
+ {
+ const svn_sort__item_t *item
+ = &APR_ARRAY_IDX(dirents_sorted, i, svn_sort__item_t);
+ svn_tree_node_t *child = item->value;
+ svn_node_kind_t child_kind;
+
+ svn_pool_clear(iterpool);
+ SVN_ERR(tree_node_get_kind_or_unknown(&child_kind, child, iterpool));
+ if (depth >= svn_depth_immediates || child_kind == svn_node_file)
+ {
+ SVN_ERR(walk_tree(child,
+ depth == svn_depth_infinity ? depth
+ : svn_depth_empty,
+ walk_func, walk_baton,
+ cancel_func, cancel_baton, iterpool));
+ }
+ }
+ svn_pool_destroy(iterpool);
+ }
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_tree_walk(svn_tree_t *tree,
+ svn_depth_t depth,
+ svn_tree_walk_func_t walk_func,
+ void *walk_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_tree_node_t *node;
+
+ SVN_ERR(svn_tree_get_root_node(&node, tree, scratch_pool, scratch_pool));
+ SVN_ERR(walk_tree(node, depth,
+ walk_func, walk_baton,
+ cancel_func, cancel_baton, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* Walk two trees, rooted at NODE1 and NODE2, simultaneously, driving the
+ * CALLBACKS.
+ *
+ * Currently visits nodes with the same relpath at the same time; see TODO
+ * notes on svn_tree_walk_two().
+ *
+ * TODO: allow recursing into a singleton directory (that is, on one side)?
+ */
+static svn_error_t *
+walk_two_trees(svn_tree_node_t *node1,
+ svn_tree_node_t *node2,
+ svn_depth_t depth,
+ const svn_tree_walk_two_func_t walk_func,
+ void *walk_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const char *relpath1 = NULL, *relpath2 = NULL;
+ svn_node_kind_t kind1 = svn_node_none, kind2 = svn_node_none;
+
+ assert(node1 || node2);
+
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
+ if (node1)
+ {
+ SVN_ERR(svn_tree_node_get_relpath(node1, &relpath1,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_tree_node_get_kind(node1, &kind1, scratch_pool));
+ }
+ if (node2)
+ {
+ SVN_ERR(svn_tree_node_get_relpath(node2, &relpath2,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_tree_node_get_kind(node2, &kind2, scratch_pool));
+ }
+ if (node1 && node2)
+ {
+ assert(strcmp(relpath1, relpath2) == 0); /* ### until move/rename support */
+ assert(kind1 == kind2); /* In Subversion a node can't change kind */
+ }
+
+ SVN_ERR(walk_func(node1, node2, walk_baton, scratch_pool));
+
+ SVN_DBG(("walk_two_trees: kind %d/%d, '%s'\n",
+ kind1, kind2, relpath1 ? relpath1 : relpath2));
+
+ /* Recurse, if it's a directory on BOTH sides */
+ if (node1 && node2
+ && kind1 == svn_node_dir
+ && depth >= svn_depth_files)
+ {
+ apr_hash_t *children1, *children2;
+ apr_hash_t *all_children;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_hash_index_t *hi;
+
+ SVN_ERR(svn_tree_node_read_dir(node1, &children1, NULL,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_tree_node_read_dir(node2, &children2, NULL,
+ scratch_pool, scratch_pool));
+ all_children = apr_hash_overlay(scratch_pool, children1, children2);
+
+ SVN_DBG(("Recursing (%d||%d=%d children) in '%s'\n",
+ apr_hash_count(children1), apr_hash_count(children2),
+ apr_hash_count(all_children),
+ relpath1));
+
+ for (hi = apr_hash_first(scratch_pool, all_children); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *relpath = svn__apr_hash_index_key(hi);
+ svn_tree_node_t *child1 = apr_hash_get(children1, relpath,
+ APR_HASH_KEY_STRING);
+ svn_tree_node_t *child2 = apr_hash_get(children2, relpath,
+ APR_HASH_KEY_STRING);
+ svn_node_kind_t child_kind;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(tree_node_get_kind_or_unknown(&child_kind,
+ child1 ? child1 : child2,
+ iterpool));
+ if (depth >= svn_depth_immediates || child_kind == svn_node_file)
+ {
+ SVN_ERR(walk_two_trees(child1, child2,
+ depth == svn_depth_infinity ? depth
+ : svn_depth_empty,
+ walk_func, walk_baton,
+ cancel_func, cancel_baton,
+ iterpool));
+ }
+ }
+ svn_pool_destroy(iterpool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_tree_walk_two(svn_tree_t *tree1,
+ svn_tree_t *tree2,
+ svn_depth_t depth,
+ const svn_tree_walk_two_func_t walk_func,
+ void *walk_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_tree_node_t *node1, *node2;
+
+ SVN_ERR(svn_tree_get_root_node(&node1, tree1, scratch_pool, scratch_pool));
+ SVN_ERR(svn_tree_get_root_node(&node2, tree2, scratch_pool, scratch_pool));
+
+ SVN_ERR(walk_two_trees(node1, node2,
+ depth,
+ walk_func, walk_baton,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* ---------------------------------------------------------------------- */
+
+svn_tree_node_t *
+svn_tree_node_create(const svn_tree_node__vtable_t *vtable,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ svn_tree_node_t *node = apr_palloc(result_pool, sizeof(*node));
+
+ node->vtable = vtable;
+ node->pool = result_pool;
+ node->priv = baton;
+ return node;
+}
+
+svn_error_t *
+svn_tree_node_get_relpath(svn_tree_node_t *node,
+ const char **relpath_p,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(node->vtable->get_relpath(node, relpath_p,
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_tree_node_get_kind(svn_tree_node_t *node,
+ svn_node_kind_t *kind_p,
+ apr_pool_t *scratch_pool)
+{
+ return node->vtable->get_kind(node, kind_p, scratch_pool);
+}
+
+svn_error_t *
+svn_tree_node_read_file(svn_tree_node_t *node,
+ svn_stream_t **stream,
+ /* svn_checksum_t **checksum, */
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return node->vtable->get_file(node, stream, props,
+ result_pool, scratch_pool);
+}
+
+svn_error_t *
+svn_tree_node_read_dir(svn_tree_node_t *node,
+ apr_hash_t **children,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return node->vtable->read_dir(node, children, props,
+ result_pool, scratch_pool);
+}
Propchange: subversion/branches/tree-read-api/subversion/libsvn_subr/tree.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: subversion/branches/tree-read-api/subversion/libsvn_wc/wc_trees.c
URL: http://svn.apache.org/viewvc/subversion/branches/tree-read-api/subversion/libsvn_wc/wc_trees.c?rev=1406709&view=auto
==============================================================================
--- subversion/branches/tree-read-api/subversion/libsvn_wc/wc_trees.c (added)
+++ subversion/branches/tree-read-api/subversion/libsvn_wc/wc_trees.c Wed Nov 7 16:33:29 2012
@@ -0,0 +1,335 @@
+/*
+ * wc_trees.c: implementation of generic tree access to a WC
+ *
+ * ====================================================================
+ * 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_types.h"
+#include "svn_pools.h"
+#include "svn_dirent_uri.h"
+#include "svn_wc.h"
+#include "svn_tree.h"
+
+#include "private/svn_tree_impl.h"
+#include "private/svn_wc_private.h"
+
+#include "svn_private_config.h"
+#include "wc.h"
+
+
+/* */
+typedef struct wc_tree_baton_t
+{
+ const char *tree_abspath;
+ svn_wc_context_t *wc_ctx;
+ svn_boolean_t is_base; /* true -> base, false -> pristine or "actual" */
+ svn_boolean_t is_pristine; /* true -> pristine, false -> base or "actual" */
+ /* "Pristine" means the WC "working" version for a mod/copy/move,
+ * but the WC "base" version for a delete/add/replace. */
+ /* "Working" means:
+ * - the WC "working" version for a mod/copy/move,
+ * - "nothing" for a delete,
+ * - ??? for an add;
+ * /replace. */
+} wc_tree_baton_t;
+
+/* */
+typedef struct wc_tree_node_baton_t
+{
+ svn_tree_t *tree;
+ const char *relpath;
+} wc_tree_node_baton_t;
+
+/* Forward declaration */
+static svn_tree_node_t *
+wc_tree_node_create(svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool);
+
+/* */
+static svn_error_t *
+wc_tree_get_node_by_relpath(svn_tree_node_t **node,
+ svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *node = wc_tree_node_create(tree, relpath, result_pool);
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+wc_treen_get_relpath(svn_tree_node_t *node,
+ const char **relpath_p,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ wc_tree_node_baton_t *nb = node->priv;
+
+ *relpath_p = nb->relpath; /* ### not duped */
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+wc_treen_get_kind(svn_tree_node_t *node,
+ svn_node_kind_t *kind,
+ apr_pool_t *scratch_pool)
+{
+ wc_tree_node_baton_t *nb = node->priv;
+ wc_tree_baton_t *tb = nb->tree->priv;
+ const char *abspath = svn_dirent_join(tb->tree_abspath, nb->relpath,
+ scratch_pool);
+
+ if (tb->is_base)
+ {
+ SVN_DBG(("oops! BASE tree not fully implemented yet: returning WORKING kind"));
+ SVN_ERR(/* ### svn_wc_read_base_kind */
+ svn_wc_read_kind(kind, tb->wc_ctx, abspath,
+ FALSE /* show_hidden */, scratch_pool));
+ }
+ else if (tb->is_pristine)
+ {
+ SVN_ERR(svn_wc_read_kind(kind, tb->wc_ctx, abspath,
+ FALSE /* show_hidden */, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_io_check_path(abspath, kind, scratch_pool));
+ }
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+wc_read_props(apr_hash_t **props,
+ wc_tree_baton_t *tb,
+ const char *abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (props)
+ {
+ if (tb->is_base)
+ {
+ SVN_ERR(svn_wc__db_base_get_props(props, tb->wc_ctx->db, abspath,
+ result_pool, scratch_pool));
+ }
+ else if (tb->is_pristine)
+ {
+ SVN_ERR(svn_wc_get_pristine_props(props, tb->wc_ctx, abspath,
+ result_pool, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_wc_prop_list2(props, tb->wc_ctx, abspath,
+ result_pool, scratch_pool));
+ }
+ }
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+wc_treen_read_file(svn_tree_node_t *node,
+ svn_stream_t **stream,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ wc_tree_node_baton_t *nb = node->priv;
+ wc_tree_baton_t *tb = nb->tree->priv;
+ const char *abspath = svn_dirent_join(tb->tree_abspath, nb->relpath,
+ scratch_pool);
+
+ if (stream)
+ {
+ if (tb->is_base)
+ {
+ const svn_checksum_t *checksum;
+
+ SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, &checksum,
+ NULL, NULL, NULL, NULL,
+ tb->wc_ctx->db, abspath,
+ scratch_pool, scratch_pool));
+ if (checksum)
+ SVN_ERR(svn_wc__db_pristine_read(stream, NULL /* size */,
+ tb->wc_ctx->db, abspath,
+ checksum,
+ result_pool, scratch_pool));
+ else
+ *stream = NULL;
+ }
+ else if (tb->is_pristine)
+ {
+ SVN_ERR(svn_wc_get_pristine_contents2(stream, tb->wc_ctx, abspath,
+ result_pool, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_stream_open_readonly(stream, abspath,
+ result_pool, scratch_pool));
+ }
+ }
+
+ SVN_ERR(wc_read_props(props, tb, abspath, result_pool, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* */
+static svn_error_t *
+wc_treen_read_dir(svn_tree_node_t *node,
+ apr_hash_t **children_p,
+ apr_hash_t **props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ wc_tree_node_baton_t *nb = node->priv;
+ wc_tree_baton_t *tb = nb->tree->priv;
+ const char *abspath = svn_dirent_join(tb->tree_abspath, nb->relpath,
+ scratch_pool);
+
+ if (children_p)
+ {
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ const apr_array_header_t *wc_children;
+ int i;
+ apr_hash_t *tree_children = apr_hash_make(result_pool);
+
+ if (tb->is_base)
+ {
+ SVN_ERR(svn_wc__db_base_get_children(
+ &wc_children, tb->wc_ctx->db, abspath,
+ result_pool, scratch_pool));
+ }
+ else if (tb->is_pristine)
+ {
+ SVN_ERR(svn_wc__node_get_children_of_working_node(
+ &wc_children, tb->wc_ctx, abspath, FALSE /* show_hidden */,
+ result_pool, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_wc__node_get_children(
+ &wc_children, tb->wc_ctx, abspath, FALSE /* show_hidden */,
+ result_pool, scratch_pool));
+ }
+
+ for (i = 0; i < wc_children->nelts; i++)
+ {
+ const char *child_abspath = APR_ARRAY_IDX(wc_children, i, const char *);
+ const char *name, *relpath;
+ svn_tree_node_t *child;
+
+ svn_pool_clear(iterpool);
+ name = svn_dirent_basename(child_abspath, iterpool);
+ relpath = svn_relpath_join(nb->relpath, name, result_pool);
+ child = wc_tree_node_create(nb->tree, relpath, result_pool);
+ apr_hash_set(tree_children, name, APR_HASH_KEY_STRING, child);
+ }
+ svn_pool_destroy(iterpool);
+
+ *children_p = tree_children;
+ }
+
+ SVN_ERR(wc_read_props(props, tb, abspath, result_pool, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* */
+static const svn_tree__vtable_t wc_tree_vtable =
+{
+ wc_tree_get_node_by_relpath
+};
+
+/* */
+static const svn_tree_node__vtable_t wc_tree_node_vtable =
+{
+ wc_treen_get_relpath,
+ wc_treen_get_kind,
+ wc_treen_read_file,
+ wc_treen_read_dir
+};
+
+/* */
+static svn_tree_node_t *
+wc_tree_node_create(svn_tree_t *tree,
+ const char *relpath,
+ apr_pool_t *result_pool)
+{
+ wc_tree_node_baton_t *nb = apr_palloc(result_pool, sizeof(*nb));
+
+ nb->tree = tree;
+ nb->relpath = relpath;
+ return svn_tree_node_create(&wc_tree_node_vtable, nb, result_pool);
+}
+
+svn_error_t *
+svn_wc__open_base_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool)
+{
+ wc_tree_baton_t *tb = apr_palloc(result_pool, sizeof(*tb));
+
+ tb->tree_abspath = abspath;
+ tb->wc_ctx = wc_ctx;
+ tb->is_base = TRUE;
+ tb->is_pristine = FALSE;
+ *tree_p = svn_tree__create(&wc_tree_vtable, tb, result_pool);
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__open_pristine_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool)
+{
+ wc_tree_baton_t *tb = apr_palloc(result_pool, sizeof(*tb));
+
+ tb->tree_abspath = abspath;
+ tb->wc_ctx = wc_ctx;
+ tb->is_base = FALSE;
+ tb->is_pristine = TRUE;
+ *tree_p = svn_tree__create(&wc_tree_vtable, tb, result_pool);
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__open_actual_tree(svn_tree_t **tree_p,
+ const char *abspath,
+ svn_wc_context_t *wc_ctx,
+ apr_pool_t *result_pool)
+{
+ wc_tree_baton_t *tb = apr_palloc(result_pool, sizeof(*tb));
+
+ tb->tree_abspath = abspath;
+ tb->wc_ctx = wc_ctx;
+ tb->is_base = FALSE;
+ tb->is_pristine = FALSE;
+ *tree_p = svn_tree__create(&wc_tree_vtable, tb, result_pool);
+ return SVN_NO_ERROR;
+}
+
Propchange: subversion/branches/tree-read-api/subversion/libsvn_wc/wc_trees.c
------------------------------------------------------------------------------
svn:eol-style = native