You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by vm...@apache.org on 2012/05/29 03:39:49 UTC
svn commit: r1343447 [12/27] - in /subversion/branches/javahl-ra: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/client-side/emacs/ contrib/server-side/ notes/
notes/api-errata/1.8/ notes/merge-tracking/ sub...
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c Tue May 29 01:39:41 2012
@@ -27,9 +27,6 @@
#include <apr_want.h>
#include <apr_uri.h>
-
-#include <expat.h>
-
#include <serf.h>
#include "svn_pools.h"
@@ -48,11 +45,13 @@
#include "private/svn_dav_protocol.h"
#include "private/svn_dep_compat.h"
#include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
#include "svn_private_config.h"
#include "ra_serf.h"
+/* Implements svn_ra__vtable_t.get_version(). */
static const svn_version_t *
ra_serf_version(void)
{
@@ -62,12 +61,14 @@ ra_serf_version(void)
#define RA_SERF_DESCRIPTION \
N_("Module for accessing a repository via WebDAV protocol using serf.")
+/* Implements svn_ra__vtable_t.get_description(). */
static const char *
ra_serf_get_description(void)
{
return _(RA_SERF_DESCRIPTION);
}
+/* Implements svn_ra__vtable_t.get_schemes(). */
static const char * const *
ra_serf_get_schemes(apr_pool_t *pool)
{
@@ -334,6 +335,7 @@ svn_ra_serf__progress(void *progress_bat
}
}
+/* Implements svn_ra__vtable_t.open_session(). */
static svn_error_t *
svn_ra_serf__open(svn_ra_session_t *session,
const char **corrected_url,
@@ -440,6 +442,7 @@ svn_ra_serf__open(svn_ra_session_t *sess
return svn_ra_serf__exchange_capabilities(serf_sess, corrected_url, pool);
}
+/* Implements svn_ra__vtable_t.reparent(). */
static svn_error_t *
svn_ra_serf__reparent(svn_ra_session_t *ra_session,
const char *url,
@@ -482,6 +485,7 @@ svn_ra_serf__reparent(svn_ra_session_t *
return SVN_NO_ERROR;
}
+/* Implements svn_ra__vtable_t.get_session_url(). */
static svn_error_t *
svn_ra_serf__get_session_url(svn_ra_session_t *ra_session,
const char **url,
@@ -492,20 +496,19 @@ svn_ra_serf__get_session_url(svn_ra_sess
return SVN_NO_ERROR;
}
+/* Implements svn_ra__vtable_t.get_latest_revnum(). */
static svn_error_t *
svn_ra_serf__get_latest_revnum(svn_ra_session_t *ra_session,
svn_revnum_t *latest_revnum,
apr_pool_t *pool)
{
- const char *relative_url, *basecoll_url;
svn_ra_serf__session_t *session = ra_session->priv;
- return svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
- NULL, session->session_url.path,
- SVN_INVALID_REVNUM, latest_revnum,
- pool);
+ return svn_error_trace(svn_ra_serf__get_youngest_revnum(
+ latest_revnum, session, pool));
}
+/* Implements svn_ra__vtable_t.rev_proplist(). */
static svn_error_t *
svn_ra_serf__rev_proplist(svn_ra_session_t *ra_session,
svn_revnum_t rev,
@@ -532,6 +535,7 @@ svn_ra_serf__rev_proplist(svn_ra_session
SVN_ERR(svn_ra_serf__discover_vcc(&propfind_path, session, NULL, pool));
}
+ /* ### fix: fetch hash of *just* the PATH@REV props. no nested hash. */
SVN_ERR(svn_ra_serf__retrieve_props(&props, session, session->conns[0],
propfind_path, rev, "0", all_props,
pool, pool));
@@ -542,6 +546,7 @@ svn_ra_serf__rev_proplist(svn_ra_session
return SVN_NO_ERROR;
}
+/* Implements svn_ra__vtable_t.rev_prop(). */
static svn_error_t *
svn_ra_serf__rev_prop(svn_ra_session_t *session,
svn_revnum_t rev,
@@ -559,71 +564,43 @@ svn_ra_serf__rev_prop(svn_ra_session_t *
}
static svn_error_t *
-fetch_path_props(svn_ra_serf__propfind_context_t **ret_prop_ctx,
- apr_hash_t **ret_props,
- const char **ret_path,
- svn_revnum_t *ret_revision,
+fetch_path_props(apr_hash_t **props,
svn_ra_serf__session_t *session,
- const char *rel_path,
+ const char *session_relpath,
svn_revnum_t revision,
const svn_ra_serf__dav_props_t *desired_props,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__propfind_context_t *prop_ctx;
- apr_hash_t *props;
- const char *path;
+ const char *url;
- path = session->session_url.path;
+ url = session->session_url.path;
/* If we have a relative path, append it. */
- if (rel_path)
- {
- path = svn_path_url_add_component2(path, rel_path, pool);
- }
-
- props = apr_hash_make(pool);
-
- /* If we were given a specific revision, we have to fetch the VCC and
- * do a PROPFIND off of that.
- */
- if (!SVN_IS_VALID_REVNUM(revision))
- {
- SVN_ERR(svn_ra_serf__deliver_props(&prop_ctx, props, session,
- session->conns[0], path, revision,
- "0", desired_props, NULL,
- pool));
- }
- else
- {
- const char *relative_url, *basecoll_url;
+ if (session_relpath)
+ url = svn_path_url_add_component2(url, session_relpath, scratch_pool);
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
- session, NULL, path,
- revision, NULL, pool));
-
- /* We will try again with our new path; however, we're now
- * technically an unversioned resource because we are accessing
- * the revision's baseline-collection.
- */
- path = svn_path_url_add_component2(basecoll_url, relative_url, pool);
- revision = SVN_INVALID_REVNUM;
- SVN_ERR(svn_ra_serf__deliver_props(&prop_ctx, props, session,
- session->conns[0], path, revision,
- "0", desired_props, NULL,
- pool));
- }
-
- /* ### switch to svn_ra_serf__retrieve_props? */
- SVN_ERR(svn_ra_serf__wait_for_props(prop_ctx, session, pool));
-
- *ret_path = path;
- *ret_prop_ctx = prop_ctx;
- *ret_props = props;
- *ret_revision = revision;
+ /* If we were given a specific revision, get a URL that refers to that
+ specific revision (rather than floating with HEAD). */
+ if (SVN_IS_VALID_REVNUM(revision))
+ {
+ SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */,
+ session, NULL /* conn */,
+ url, revision,
+ scratch_pool, scratch_pool));
+ }
+
+ /* URL is stable, so we use SVN_INVALID_REVNUM since it is now irrelevant.
+ Or we started with SVN_INVALID_REVNUM and URL may be floating. */
+ SVN_ERR(svn_ra_serf__fetch_node_props(props, session->conns[0],
+ url, SVN_INVALID_REVNUM,
+ desired_props,
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
+/* Implements svn_ra__vtable_t.check_path(). */
static svn_error_t *
svn_ra_serf__check_path(svn_ra_session_t *ra_session,
const char *rel_path,
@@ -633,13 +610,10 @@ svn_ra_serf__check_path(svn_ra_session_t
{
svn_ra_serf__session_t *session = ra_session->priv;
apr_hash_t *props;
- svn_ra_serf__propfind_context_t *prop_ctx;
- const char *path;
- svn_revnum_t fetched_rev;
- svn_error_t *err = fetch_path_props(&prop_ctx, &props, &path, &fetched_rev,
- session, rel_path,
- revision, check_path_props, pool);
+ svn_error_t *err = fetch_path_props(&props, session, rel_path,
+ revision, check_path_props,
+ pool, pool);
if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
{
@@ -648,11 +622,14 @@ svn_ra_serf__check_path(svn_ra_session_t
}
else
{
+ svn_kind_t res_kind;
+
/* Any other error, raise to caller. */
if (err)
- return err;
+ return svn_error_trace(err);
- SVN_ERR(svn_ra_serf__get_resource_type(kind, props, path, fetched_rev));
+ SVN_ERR(svn_ra_serf__get_resource_type(&res_kind, props));
+ *kind = svn__node_kind_from_kind(res_kind);
}
return SVN_NO_ERROR;
@@ -862,6 +839,7 @@ get_dirent_props(apr_uint32_t dirent_fie
return (svn_ra_serf__dav_props_t *) props->elts;
}
+/* Implements svn_ra__vtable_t.stat(). */
static svn_error_t *
svn_ra_serf__stat(svn_ra_session_t *ra_session,
const char *rel_path,
@@ -871,17 +849,14 @@ svn_ra_serf__stat(svn_ra_session_t *ra_s
{
svn_ra_serf__session_t *session = ra_session->priv;
apr_hash_t *props;
- svn_ra_serf__propfind_context_t *prop_ctx;
- const char *path;
- svn_revnum_t fetched_rev;
svn_error_t *err;
struct dirent_walker_baton_t dwb;
svn_tristate_t deadprop_count = svn_tristate_unknown;
- err = fetch_path_props(&prop_ctx, &props, &path, &fetched_rev,
+ err = fetch_path_props(&props,
session, rel_path, revision,
get_dirent_props(SVN_DIRENT_ALL, session, pool),
- pool);
+ pool, pool);
if (err)
{
if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
@@ -897,9 +872,7 @@ svn_ra_serf__stat(svn_ra_session_t *ra_s
dwb.entry = apr_pcalloc(pool, sizeof(*dwb.entry));
dwb.supports_deadprop_count = &deadprop_count;
dwb.result_pool = pool;
- SVN_ERR(svn_ra_serf__walk_all_props(props, path, fetched_rev,
- dirent_walker, &dwb,
- pool));
+ SVN_ERR(svn_ra_serf__walk_node_props(props, dirent_walker, &dwb, pool));
if (deadprop_count == svn_tristate_false
&& session->supports_deadprop_count == svn_tristate_unknown
@@ -909,14 +882,12 @@ svn_ra_serf__stat(svn_ra_session_t *ra_s
information */
session->supports_deadprop_count = svn_tristate_false;
- SVN_ERR(fetch_path_props(&prop_ctx, &props, &path, &fetched_rev,
- session, rel_path, fetched_rev,
+ SVN_ERR(fetch_path_props(&props,
+ session, rel_path, SVN_INVALID_REVNUM,
get_dirent_props(SVN_DIRENT_ALL, session, pool),
- pool));
+ pool, pool));
- SVN_ERR(svn_ra_serf__walk_all_props(props, path, fetched_rev,
- dirent_walker, &dwb,
- pool));
+ SVN_ERR(svn_ra_serf__walk_node_props(props, dirent_walker, &dwb, pool));
}
if (deadprop_count != svn_tristate_unknown)
@@ -932,15 +903,13 @@ svn_ra_serf__stat(svn_ra_session_t *ra_s
* SVN_ERR_FS_NOT_DIRECTORY if not.
*/
static svn_error_t *
-resource_is_directory(apr_hash_t *props,
- const char *path,
- svn_revnum_t revision)
+resource_is_directory(apr_hash_t *props)
{
- svn_node_kind_t kind;
+ svn_kind_t kind;
- SVN_ERR(svn_ra_serf__get_resource_type(&kind, props, path, revision));
+ SVN_ERR(svn_ra_serf__get_resource_type(&kind, props));
- if (kind != svn_node_dir)
+ if (kind != svn_kind_dir)
{
return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
_("Can't get entries of non-directory"));
@@ -949,6 +918,7 @@ resource_is_directory(apr_hash_t *props,
return SVN_NO_ERROR;
}
+/* Implements svn_ra__vtable_t.get_dir(). */
static svn_error_t *
svn_ra_serf__get_dir(svn_ra_session_t *ra_session,
apr_hash_t **dirents,
@@ -975,34 +945,37 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
public url. */
if (SVN_IS_VALID_REVNUM(revision) || fetched_rev)
{
- const char *relative_url, *basecoll_url;
-
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url,
- session, NULL, path, revision,
- fetched_rev, pool));
-
- path = svn_path_url_add_component2(basecoll_url, relative_url, pool);
+ SVN_ERR(svn_ra_serf__get_stable_url(&path, fetched_rev,
+ session, NULL /* conn */,
+ path, revision,
+ pool, pool));
revision = SVN_INVALID_REVNUM;
}
+ /* REVISION is always SVN_INVALID_REVNUM */
+ SVN_ERR_ASSERT(!SVN_IS_VALID_REVNUM(revision));
/* If we're asked for children, fetch them now. */
if (dirents)
{
struct path_dirent_visitor_t dirent_walk;
apr_hash_t *props;
+ const char *rtype;
/* Always request node kind to check that path is really a
* directory.
*/
dirent_fields |= SVN_DIRENT_KIND;
SVN_ERR(svn_ra_serf__retrieve_props(&props, session, session->conns[0],
- path, revision, "1",
+ path, SVN_INVALID_REVNUM, "1",
get_dirent_props(dirent_fields,
session, pool),
pool, pool));
/* Check if the path is really a directory. */
- SVN_ERR(resource_is_directory(props, path, revision));
+ rtype = svn_ra_serf__get_prop(props, path, "DAV:", "resourcetype");
+ if (rtype == NULL || strcmp(rtype, "collection") != 0)
+ return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
+ _("Can't get entries of non-directory"));
/* We're going to create two hashes to help the walker along.
* We're going to return the 2nd one back to the caller as it
@@ -1014,8 +987,9 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
dirent_walk.supports_deadprop_count = svn_tristate_unknown;
dirent_walk.result_pool = pool;
- SVN_ERR(svn_ra_serf__walk_all_paths(props, revision, path_dirent_walker,
- &dirent_walk, pool));
+ SVN_ERR(svn_ra_serf__walk_all_paths(props, SVN_INVALID_REVNUM,
+ path_dirent_walker, &dirent_walk,
+ pool));
if (dirent_walk.supports_deadprop_count == svn_tristate_false
&& session->supports_deadprop_count == svn_tristate_unknown
@@ -1026,7 +1000,7 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
session->supports_deadprop_count = svn_tristate_false;
SVN_ERR(svn_ra_serf__retrieve_props(&props, session,
session->conns[0],
- path, revision, "1",
+ path, SVN_INVALID_REVNUM, "1",
get_dirent_props(dirent_fields,
session, pool),
pool, pool));
@@ -1034,7 +1008,7 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
SVN_ERR(svn_hash__clear(dirent_walk.full_paths, pool));
SVN_ERR(svn_hash__clear(dirent_walk.base_paths, pool));
- SVN_ERR(svn_ra_serf__walk_all_paths(props, revision,
+ SVN_ERR(svn_ra_serf__walk_all_paths(props, SVN_INVALID_REVNUM,
path_dirent_walker,
&dirent_walk, pool));
}
@@ -1050,14 +1024,17 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
{
apr_hash_t *props;
- SVN_ERR(svn_ra_serf__retrieve_props(&props, session, session->conns[0],
- path, revision, "0", all_props,
- pool, pool));
+ SVN_ERR(svn_ra_serf__fetch_node_props(&props, session->conns[0],
+ path, SVN_INVALID_REVNUM,
+ all_props,
+ pool, pool));
+
/* Check if the path is really a directory. */
- SVN_ERR(resource_is_directory(props, path, revision));
+ SVN_ERR(resource_is_directory(props));
- SVN_ERR(svn_ra_serf__flatten_props(ret_props, props, path, revision,
- pool, pool));
+ /* ### flatten_props() does not copy PROPVALUE, but fetch_node_props()
+ ### put them into POOL, so we're okay. */
+ SVN_ERR(svn_ra_serf__flatten_props(ret_props, props, pool, pool));
}
return SVN_NO_ERROR;
@@ -1088,6 +1065,8 @@ svn_ra_serf__get_repos_root(svn_ra_sessi
case where the root of the repository is not readable.
However, it does not handle the case where we're fetching path not existing
in HEAD of a repository with unreadable root directory.
+
+ Implements svn_ra__vtable_t.get_uuid().
*/
static svn_error_t *
svn_ra_serf__get_uuid(svn_ra_session_t *ra_session,
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c Tue May 29 01:39:41 2012
@@ -126,17 +126,10 @@ typedef struct report_dir_t
/* Our base revision - SVN_INVALID_REVNUM if we're adding this dir. */
svn_revnum_t base_rev;
- /* The target revision we're retrieving. */
- svn_revnum_t target_rev;
-
/* controlling dir baton - this is only created in open_dir() */
void *dir_baton;
apr_pool_t *dir_baton_pool;
- /* Our master update editor and baton. */
- const svn_delta_editor_t *update_editor;
- void *update_baton;
-
/* How many references to this directory do we still have open? */
apr_size_t ref_count;
@@ -200,9 +193,6 @@ typedef struct report_info_t
/* Our base revision - SVN_INVALID_REVNUM if we're adding this file. */
svn_revnum_t base_rev;
- /* The target revision we're retrieving. */
- svn_revnum_t target_rev;
-
/* our delta base, if present (NULL if we're adding the file) */
const char *delta_base;
@@ -237,6 +227,10 @@ typedef struct report_info_t
/* Checksum for close_file */
const char *final_checksum;
+ /* Stream containing file contents already cached in the working
+ copy (which may be used to avoid a GET request for the same). */
+ svn_stream_t *cached_contents;
+
/* temporary property for this file which is currently being parsed
* It will eventually be stored in our parent directory's property hash.
*/
@@ -252,6 +246,9 @@ typedef struct report_info_t
*/
typedef struct report_fetch_t {
+ /* The handler representing this particular fetch. */
+ svn_ra_serf__handler_t *handler;
+
/* The session we should use to fetch the file. */
svn_ra_serf__session_t *sess;
@@ -349,7 +346,7 @@ struct report_context_t {
/* number of pending PROPFIND requests */
unsigned int active_propfinds;
- /* completed PROPFIND requests (contains propfind_context_t) */
+ /* completed PROPFIND requests (contains svn_ra_serf__propfind_context_t) */
svn_ra_serf__list_t *done_propfinds;
/* list of files that only have prop changes (contains report_info_t) */
@@ -407,9 +404,6 @@ push_state(svn_ra_serf__xml_parser_t *pa
new_info->props = new_info->dir->props;
new_info->dir->removed_props = apr_hash_make(new_info->pool);
- /* Point to the update_editor */
- new_info->dir->update_editor = ctx->update_editor;
- new_info->dir->update_baton = ctx->update_baton;
new_info->dir->report_context = ctx;
if (info)
@@ -467,7 +461,7 @@ set_file_props(void *baton,
apr_pool_t *scratch_pool)
{
report_info_t *info = baton;
- const svn_delta_editor_t *editor = info->dir->update_editor;
+ const svn_delta_editor_t *editor = info->dir->report_context->update_editor;
const char *prop_name;
if (strcmp(name, "md5-checksum") == 0
@@ -492,7 +486,7 @@ set_dir_props(void *baton,
apr_pool_t *scratch_pool)
{
report_dir_t *dir = baton;
- const svn_delta_editor_t *editor = dir->update_editor;
+ const svn_delta_editor_t *editor = dir->report_context->update_editor;
const char *prop_name;
prop_name = svn_ra_serf__svnname_from_wirename(ns, name, scratch_pool);
@@ -513,7 +507,7 @@ remove_file_props(void *baton,
apr_pool_t *scratch_pool)
{
report_info_t *info = baton;
- const svn_delta_editor_t *editor = info->dir->update_editor;
+ const svn_delta_editor_t *editor = info->dir->report_context->update_editor;
const char *prop_name;
prop_name = svn_ra_serf__svnname_from_wirename(ns, name, scratch_pool);
@@ -534,7 +528,7 @@ remove_dir_props(void *baton,
apr_pool_t *scratch_pool)
{
report_dir_t *dir = baton;
- const svn_delta_editor_t *editor = dir->update_editor;
+ const svn_delta_editor_t *editor = dir->report_context->update_editor;
const char *prop_name;
prop_name = svn_ra_serf__svnname_from_wirename(ns, name, scratch_pool);
@@ -552,6 +546,8 @@ remove_dir_props(void *baton,
static svn_error_t*
open_dir(report_dir_t *dir)
{
+ report_context_t *ctx = dir->report_context;
+
/* if we're already open, return now */
if (dir->dir_baton)
{
@@ -562,16 +558,16 @@ open_dir(report_dir_t *dir)
{
dir->dir_baton_pool = svn_pool_create(dir->pool);
- if (dir->report_context->destination &&
- dir->report_context->sess->wc_callbacks->invalidate_wc_props)
+ if (ctx->destination
+ && ctx->sess->wc_callbacks->invalidate_wc_props)
{
- SVN_ERR(dir->report_context->sess->wc_callbacks->invalidate_wc_props(
- dir->report_context->sess->wc_callback_baton,
- dir->report_context->update_target,
+ SVN_ERR(ctx->sess->wc_callbacks->invalidate_wc_props(
+ ctx->sess->wc_callback_baton,
+ ctx->update_target,
SVN_RA_SERF__WC_CHECKED_IN_URL, dir->pool));
}
- SVN_ERR(dir->update_editor->open_root(dir->update_baton, dir->base_rev,
+ SVN_ERR(ctx->update_editor->open_root(ctx->update_baton, dir->base_rev,
dir->dir_baton_pool,
&dir->dir_baton));
}
@@ -583,7 +579,7 @@ open_dir(report_dir_t *dir)
if (SVN_IS_VALID_REVNUM(dir->base_rev))
{
- SVN_ERR(dir->update_editor->open_directory(dir->name,
+ SVN_ERR(ctx->update_editor->open_directory(dir->name,
dir->parent_dir->dir_baton,
dir->base_rev,
dir->dir_baton_pool,
@@ -591,7 +587,7 @@ open_dir(report_dir_t *dir)
}
else
{
- SVN_ERR(dir->update_editor->add_directory(dir->name,
+ SVN_ERR(ctx->update_editor->add_directory(dir->name,
dir->parent_dir->dir_baton,
NULL, SVN_INVALID_REVNUM,
dir->dir_baton_pool,
@@ -625,12 +621,13 @@ close_dir(report_dir_t *dir)
if (dir->fetch_props)
{
SVN_ERR(svn_ra_serf__walk_all_props(dir->props, dir->url,
- dir->target_rev,
+ dir->report_context->target_rev,
set_dir_props, dir,
scratch_pool));
}
- SVN_ERR(dir->update_editor->close_directory(dir->dir_baton, scratch_pool));
+ SVN_ERR(dir->report_context->update_editor->close_directory(
+ dir->dir_baton, scratch_pool));
/* remove us from our parent's children list */
if (dir->parent_dir)
@@ -694,7 +691,7 @@ check_lock(report_info_t *info)
const char *lock_val;
lock_val = svn_ra_serf__get_ver_prop(info->props, info->url,
- info->target_rev,
+ info->dir->report_context->target_rev,
"DAV:", "lockdiscovery");
if (lock_val)
@@ -801,6 +798,105 @@ error_fetch(serf_request_t *request,
return err;
}
+/* Wield the editor referenced by INFO to open (or add) the file
+ file also associated with INFO, setting properties on the file and
+ calling the editor's apply_textdelta() function on it if necessary
+ (or if FORCE_APPLY_TEXTDELTA is set).
+
+ Callers will probably want to also see the function that serves
+ the opposite purpose of this one, close_updated_file(). */
+static svn_error_t *
+open_updated_file(report_info_t *info,
+ svn_boolean_t force_apply_textdelta,
+ apr_pool_t *scratch_pool)
+{
+ report_context_t *ctx = info->dir->report_context;
+ const svn_delta_editor_t *update_editor = ctx->update_editor;
+
+ /* Ensure our parent is open. */
+ SVN_ERR(open_dir(info->dir));
+ info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
+
+ /* Expand our full name now if we haven't done so yet. */
+ if (!info->name)
+ {
+ info->name = svn_relpath_join(info->dir->name, info->base_name,
+ info->editor_pool);
+ }
+
+ /* Open (or add) the file. */
+ if (SVN_IS_VALID_REVNUM(info->base_rev))
+ {
+ SVN_ERR(update_editor->open_file(info->name,
+ info->dir->dir_baton,
+ info->base_rev,
+ info->editor_pool,
+ &info->file_baton));
+ }
+ else
+ {
+ SVN_ERR(update_editor->add_file(info->name,
+ info->dir->dir_baton,
+ info->copyfrom_path,
+ info->copyfrom_rev,
+ info->editor_pool,
+ &info->file_baton));
+ }
+
+ /* Check for lock information. */
+ if (info->lock_token)
+ check_lock(info);
+
+ /* Set all of the properties we received */
+ SVN_ERR(svn_ra_serf__walk_all_props(info->props,
+ info->base_name,
+ info->base_rev,
+ set_file_props, info,
+ scratch_pool));
+ SVN_ERR(svn_ra_serf__walk_all_props(info->dir->removed_props,
+ info->base_name,
+ info->base_rev,
+ remove_file_props, info,
+ scratch_pool));
+ if (info->fetch_props)
+ {
+ SVN_ERR(svn_ra_serf__walk_all_props(info->props,
+ info->url,
+ ctx->target_rev,
+ set_file_props, info,
+ scratch_pool));
+ }
+
+ /* Get (maybe) a textdelta window handler for transmitting file
+ content changes. */
+ if (info->fetch_file || force_apply_textdelta)
+ {
+ SVN_ERR(update_editor->apply_textdelta(info->file_baton,
+ info->base_checksum,
+ info->editor_pool,
+ &info->textdelta,
+ &info->textdelta_baton));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Close the file associated with INFO->file_baton, and cleanup other
+ bits of that structure managed by open_updated_file(). */
+static svn_error_t *
+close_updated_file(report_info_t *info,
+ apr_pool_t *scratch_pool)
+{
+ /* Close the file via the editor. */
+ SVN_ERR(info->dir->report_context->update_editor->close_file(
+ info->file_baton, info->final_checksum, scratch_pool));
+
+ /* We're done with our editor pool. */
+ svn_pool_destroy(info->editor_pool);
+
+ return SVN_NO_ERROR;
+}
+
/* Implements svn_ra_serf__response_handler_t */
static svn_error_t *
handle_fetch(serf_request_t *request,
@@ -813,7 +909,9 @@ handle_fetch(serf_request_t *request,
apr_status_t status;
report_fetch_t *fetch_ctx = handler_baton;
svn_error_t *err;
- serf_status_line sl;
+
+ /* ### new field. make sure we didn't miss some initialization. */
+ SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
if (fetch_ctx->read_headers == FALSE)
{
@@ -825,50 +923,8 @@ handle_fetch(serf_request_t *request,
val = serf_bucket_headers_get(hdrs, "Content-Type");
info = fetch_ctx->info;
- err = open_dir(info->dir);
- if (err)
- {
- return error_fetch(request, fetch_ctx, err);
- }
-
- info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
-
- /* Expand our full name now if we haven't done so yet. */
- if (!info->name)
- {
- info->name = svn_relpath_join(info->dir->name, info->base_name,
- info->editor_pool);
- }
-
- if (SVN_IS_VALID_REVNUM(info->base_rev))
- {
- err = info->dir->update_editor->open_file(info->name,
- info->dir->dir_baton,
- info->base_rev,
- info->editor_pool,
- &info->file_baton);
- }
- else
- {
- err = info->dir->update_editor->add_file(info->name,
- info->dir->dir_baton,
- info->copyfrom_path,
- info->copyfrom_rev,
- info->editor_pool,
- &info->file_baton);
- }
-
- if (err)
- {
- return error_fetch(request, fetch_ctx, err);
- }
-
- err = info->dir->update_editor->apply_textdelta(info->file_baton,
- info->base_checksum,
- info->editor_pool,
- &info->textdelta,
- &info->textdelta_baton);
-
+ /* Open the file for editing. */
+ err = open_updated_file(info, FALSE, info->pool);
if (err)
{
return error_fetch(request, fetch_ctx, err);
@@ -891,16 +947,12 @@ handle_fetch(serf_request_t *request,
/* If the error code wasn't 200, something went wrong. Don't use the returned
data as its probably an error message. Just bail out instead. */
- status = serf_bucket_response_status(response, &sl);
- if (SERF_BUCKET_READ_ERROR(status))
- {
- return svn_error_wrap_apr(status, NULL);
- }
- if (sl.code != 200)
+ if (fetch_ctx->handler->sline.code != 200)
{
err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("GET request failed: %d %s"),
- sl.code, sl.reason);
+ fetch_ctx->handler->sline.code,
+ fetch_ctx->handler->sline.reason);
return error_fetch(request, fetch_ctx, err);
}
@@ -983,51 +1035,17 @@ handle_fetch(serf_request_t *request,
{
report_info_t *info = fetch_ctx->info;
- /* ### this doesn't feel quite right. but it gets tossed at the
- ### end of this block, so it will work for now. */
- apr_pool_t *scratch_pool = info->editor_pool;
-
if (fetch_ctx->delta_stream)
err = svn_error_trace(svn_stream_close(fetch_ctx->delta_stream));
else
err = svn_error_trace(info->textdelta(NULL,
info->textdelta_baton));
-
if (err)
{
return error_fetch(request, fetch_ctx, err);
}
- if (info->lock_token)
- check_lock(info);
-
- /* set all of the properties we received */
- err = svn_ra_serf__walk_all_props(info->props,
- info->base_name,
- info->base_rev,
- set_file_props, info,
- scratch_pool);
-
- if (!err)
- err = svn_ra_serf__walk_all_props(info->dir->removed_props,
- info->base_name,
- info->base_rev,
- remove_file_props, info,
- scratch_pool);
- if (!err && info->fetch_props)
- {
- err = svn_ra_serf__walk_all_props(info->props,
- info->url,
- info->target_rev,
- set_file_props, info,
- scratch_pool);
- }
-
- if (!err)
- err = info->dir->update_editor->close_file(info->file_baton,
- info->final_checksum,
- scratch_pool);
-
+ err = close_updated_file(info, info->pool);
if (err)
{
return svn_error_trace(error_fetch(request, fetch_ctx, err));
@@ -1039,8 +1057,7 @@ handle_fetch(serf_request_t *request,
fetch_ctx->done_item.next = *fetch_ctx->done_list;
*fetch_ctx->done_list = &fetch_ctx->done_item;
- /* We're done with our pools. */
- svn_pool_destroy(info->editor_pool);
+ /* We're done with our pool. */
svn_pool_destroy(info->pool);
if (status)
@@ -1062,26 +1079,22 @@ handle_stream(serf_request_t *request,
apr_pool_t *pool)
{
report_fetch_t *fetch_ctx = handler_baton;
- serf_status_line sl;
const char *location;
svn_error_t *err;
apr_status_t status;
- status = serf_bucket_response_status(response, &sl);
- if (SERF_BUCKET_READ_ERROR(status))
- {
- return svn_error_wrap_apr(status, NULL);
- }
+ /* ### new field. make sure we didn't miss some initialization. */
+ SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
/* Woo-hoo. Nothing here to see. */
location = svn_ra_serf__response_get_location(response, pool);
- err = svn_ra_serf__error_on_status(sl.code,
+ err = svn_ra_serf__error_on_status(fetch_ctx->handler->sline.code,
fetch_ctx->info->name,
location);
if (err)
{
- fetch_ctx->done = TRUE;
+ fetch_ctx->handler->done = TRUE;
err = svn_error_compose_create(
err,
@@ -1157,78 +1170,100 @@ static svn_error_t *
handle_propchange_only(report_info_t *info,
apr_pool_t *scratch_pool)
{
- /* Ensure our parent is open. */
- SVN_ERR(open_dir(info->dir));
+ /* Open the file for editing (without forcing an apply_textdelta),
+ pass along any propchanges we've recorded for it, and then close
+ the file. */
+ SVN_ERR(open_updated_file(info, FALSE, scratch_pool));
+ SVN_ERR(close_updated_file(info, scratch_pool));
+
+ /* We're done with our pool. */
+ svn_pool_destroy(info->pool);
- info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
+ info->dir->ref_count--;
- /* Expand our full name now if we haven't done so yet. */
- if (!info->name)
- {
- info->name = svn_relpath_join(info->dir->name, info->base_name,
- info->editor_pool);
- }
+ return SVN_NO_ERROR;
+}
- if (SVN_IS_VALID_REVNUM(info->base_rev))
- {
- SVN_ERR(info->dir->update_editor->open_file(info->name,
- info->dir->dir_baton,
- info->base_rev,
- info->editor_pool,
- &info->file_baton));
- }
- else
- {
- SVN_ERR(info->dir->update_editor->add_file(info->name,
- info->dir->dir_baton,
- info->copyfrom_path,
- info->copyfrom_rev,
- info->editor_pool,
- &info->file_baton));
- }
+/* "Fetch" a file whose contents were made available via the
+ get_wc_contents() callback (as opposed to requiring a GET to the
+ server), and feed the information through the associated update
+ editor. */
+static svn_error_t *
+local_fetch(report_info_t *info,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(open_updated_file(info, TRUE, scratch_pool));
+
+ SVN_ERR(svn_txdelta_send_stream(info->cached_contents, info->textdelta,
+ info->textdelta_baton, NULL, scratch_pool));
+ SVN_ERR(svn_stream_close(info->cached_contents));
+ info->cached_contents = NULL;
+ SVN_ERR(close_updated_file(info, scratch_pool));
- if (info->fetch_file)
- {
- SVN_ERR(info->dir->update_editor->apply_textdelta(info->file_baton,
- info->base_checksum,
- info->editor_pool,
- &info->textdelta,
- &info->textdelta_baton));
- }
+ /* We're done with our pool. */
+ svn_pool_destroy(info->pool);
- if (info->lock_token)
- check_lock(info);
+ return SVN_NO_ERROR;
+}
- /* set all of the properties we received */
- SVN_ERR(svn_ra_serf__walk_all_props(info->props,
- info->base_name, info->base_rev,
- set_file_props, info,
- scratch_pool));
- SVN_ERR(svn_ra_serf__walk_all_props(info->dir->removed_props,
- info->base_name, info->base_rev,
- remove_file_props, info,
- scratch_pool));
- if (info->fetch_props)
- {
- SVN_ERR(svn_ra_serf__walk_all_props(info->props, info->url,
- info->target_rev,
- set_file_props, info,
- scratch_pool));
- }
+/* Implements svn_ra_serf__response_handler_t */
+static svn_error_t *
+handle_local_fetch(serf_request_t *request,
+ serf_bucket_t *response,
+ void *handler_baton,
+ apr_pool_t *pool)
+{
+ report_fetch_t *fetch_ctx = handler_baton;
+ apr_status_t status;
+ svn_error_t *err;
+ const char *data;
+ apr_size_t len;
- SVN_ERR(info->dir->update_editor->close_file(info->file_baton,
- info->final_checksum,
- scratch_pool));
+ /* ### new field. make sure we didn't miss some initialization. */
+ SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
- /* We're done with our pools. */
- svn_pool_destroy(info->editor_pool);
- svn_pool_destroy(info->pool);
+ /* If the error code wasn't 200, something went wrong. Don't use the returned
+ data as its probably an error message. Just bail out instead. */
+ if (fetch_ctx->handler->sline.code != 200)
+ {
+ err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+ _("HEAD request failed: %d %s"),
+ fetch_ctx->handler->sline.code,
+ fetch_ctx->handler->sline.reason);
+ return error_fetch(request, fetch_ctx, err);
+ }
- info->dir->ref_count--;
+ while (1)
+ {
+ status = serf_bucket_read(response, 8000, &data, &len);
+ if (SERF_BUCKET_READ_ERROR(status))
+ {
+ return svn_error_wrap_apr(status, NULL);
+ }
+ if (APR_STATUS_IS_EOF(status))
+ {
+ err = local_fetch(fetch_ctx->info, fetch_ctx->info->pool);
+ if (err)
+ {
+ return error_fetch(request, fetch_ctx, err);
+ }
- return SVN_NO_ERROR;
+ fetch_ctx->done = TRUE;
+ fetch_ctx->done_item.data = fetch_ctx;
+ fetch_ctx->done_item.next = *fetch_ctx->done_list;
+ *fetch_ctx->done_list = &fetch_ctx->done_item;
+ return svn_error_wrap_apr(status, NULL);
+ }
+ if (APR_STATUS_IS_EAGAIN(status))
+ {
+ return svn_error_wrap_apr(status, NULL);
+ }
+ }
+ /* not reached */
}
+/* --------------------------------------------------------- */
+
static svn_error_t *
fetch_file(report_context_t *ctx, report_info_t *info)
{
@@ -1239,9 +1274,8 @@ fetch_file(report_context_t *ctx, report
conn = ctx->sess->conns[ctx->sess->cur_conn];
/* go fetch info->name from DAV:checked-in */
- info->url =
- svn_ra_serf__get_ver_prop(info->props, info->base_name,
- info->base_rev, "DAV:", "checked-in");
+ info->url = svn_ra_serf__get_ver_prop(info->props, info->base_name,
+ info->base_rev, "DAV:", "checked-in");
if (!info->url)
{
@@ -1256,7 +1290,7 @@ fetch_file(report_context_t *ctx, report
{
SVN_ERR(svn_ra_serf__deliver_props(&info->propfind, info->props,
ctx->sess, conn, info->url,
- info->target_rev, "0", all_props,
+ ctx->target_rev, "0", all_props,
&ctx->done_propfinds,
info->dir->pool));
SVN_ERR_ASSERT(info->propfind);
@@ -1269,34 +1303,104 @@ fetch_file(report_context_t *ctx, report
*/
if (info->fetch_file && ctx->text_deltas)
{
- report_fetch_t *fetch_ctx;
+ svn_stream_t *contents = NULL;
- fetch_ctx = apr_pcalloc(info->dir->pool, sizeof(*fetch_ctx));
- fetch_ctx->info = info;
- fetch_ctx->done_list = &ctx->done_fetches;
- fetch_ctx->sess = ctx->sess;
- fetch_ctx->conn = conn;
+ if (ctx->sess->wc_callbacks->get_wc_contents
+ && info->final_sha1_checksum)
+ {
+ svn_error_t *err;
+ svn_checksum_t *sha1_checksum;
- handler = apr_pcalloc(info->dir->pool, sizeof(*handler));
+ err = svn_checksum_parse_hex(&sha1_checksum, svn_checksum_sha1,
+ info->final_sha1_checksum, info->pool);
+ if (!err)
+ {
+ err = ctx->sess->wc_callbacks->get_wc_contents(
+ ctx->sess->wc_callback_baton, &contents,
+ sha1_checksum, info->pool);
+ }
- handler->method = "GET";
- handler->path = fetch_ctx->info->url;
+ if (err)
+ {
+ /* Meh. Maybe we'll care one day why we're in an
+ errorful state, but this codepath is optional. */
+ svn_error_clear(err);
+ }
+ else
+ {
+ info->cached_contents = contents;
+ }
+ }
- handler->conn = conn;
- handler->session = ctx->sess;
+ /* If the working copy can provided cached contents for this
+ file, we'll send a simple HEAD request (which I'll claim is
+ to verify readability, but really is just so I can provide a
+ Serf-queued-request-compliant way of processing the contents
+ after the PROPFIND for the file's properties ... ugh).
- handler->header_delegate = headers_fetch;
- handler->header_delegate_baton = fetch_ctx;
+ Otherwise, we use a GET request for the file's contents. */
+ if (info->cached_contents)
+ {
+ report_fetch_t *fetch_ctx;
- handler->response_handler = handle_fetch;
- handler->response_baton = fetch_ctx;
+ fetch_ctx = apr_pcalloc(info->dir->pool, sizeof(*fetch_ctx));
+ fetch_ctx->info = info;
+ fetch_ctx->done_list = &ctx->done_fetches;
+ fetch_ctx->sess = ctx->sess;
+ fetch_ctx->conn = conn;
- handler->response_error = cancel_fetch;
- handler->response_error_baton = fetch_ctx;
+ handler = apr_pcalloc(info->dir->pool, sizeof(*handler));
- svn_ra_serf__request_create(handler);
+ handler->handler_pool = info->dir->pool;
+ handler->method = "HEAD";
+ handler->path = fetch_ctx->info->url;
+
+ handler->conn = conn;
+ handler->session = ctx->sess;
+
+ handler->response_handler = handle_local_fetch;
+ handler->response_baton = fetch_ctx;
+
+ fetch_ctx->handler = handler;
+
+ svn_ra_serf__request_create(handler);
+
+ ctx->active_fetches++;
+ }
+ else
+ {
+ report_fetch_t *fetch_ctx;
- ctx->active_fetches++;
+ fetch_ctx = apr_pcalloc(info->dir->pool, sizeof(*fetch_ctx));
+ fetch_ctx->info = info;
+ fetch_ctx->done_list = &ctx->done_fetches;
+ fetch_ctx->sess = ctx->sess;
+ fetch_ctx->conn = conn;
+
+ handler = apr_pcalloc(info->dir->pool, sizeof(*handler));
+
+ handler->handler_pool = info->dir->pool;
+ handler->method = "GET";
+ handler->path = fetch_ctx->info->url;
+
+ handler->conn = conn;
+ handler->session = ctx->sess;
+
+ handler->header_delegate = headers_fetch;
+ handler->header_delegate_baton = fetch_ctx;
+
+ handler->response_handler = handle_fetch;
+ handler->response_baton = fetch_ctx;
+
+ handler->response_error = cancel_fetch;
+ handler->response_error_baton = fetch_ctx;
+
+ fetch_ctx->handler = handler;
+
+ svn_ra_serf__request_create(handler);
+
+ ctx->active_fetches++;
+ }
}
else if (info->propfind)
{
@@ -1373,7 +1477,6 @@ start_report(svn_ra_serf__xml_parser_t *
info->base_rev = SVN_STR_TO_REV(rev);
info->dir->base_rev = info->base_rev;
- info->dir->target_rev = ctx->target_rev;
info->fetch_props = TRUE;
info->dir->base_name = "";
@@ -1426,7 +1529,6 @@ start_report(svn_ra_serf__xml_parser_t *
info->base_rev = SVN_STR_TO_REV(rev);
dir->base_rev = info->base_rev;
- dir->target_rev = ctx->target_rev;
info->fetch_props = FALSE;
@@ -1480,7 +1582,6 @@ start_report(svn_ra_serf__xml_parser_t *
/* Mark that we don't have a base. */
info->base_rev = SVN_INVALID_REVNUM;
dir->base_rev = info->base_rev;
- dir->target_rev = ctx->target_rev;
dir->fetch_props = TRUE;
dir->repos_relpath = svn_relpath_join(dir->parent_dir->repos_relpath,
@@ -1513,7 +1614,6 @@ start_report(svn_ra_serf__xml_parser_t *
info = push_state(parser, ctx, OPEN_FILE);
info->base_rev = SVN_STR_TO_REV(rev);
- info->target_rev = ctx->target_rev;
info->fetch_props = FALSE;
info->base_name = apr_pstrdup(info->pool, file_name);
@@ -1539,7 +1639,6 @@ start_report(svn_ra_serf__xml_parser_t *
info = push_state(parser, ctx, ADD_FILE);
info->base_rev = SVN_INVALID_REVNUM;
- info->target_rev = ctx->target_rev;
info->fetch_props = TRUE;
info->fetch_file = TRUE;
@@ -1586,10 +1685,10 @@ start_report(svn_ra_serf__xml_parser_t *
full_path = svn_relpath_join(info->dir->name, file_name, tmppool);
- SVN_ERR(info->dir->update_editor->delete_entry(full_path,
- delete_rev,
- info->dir->dir_baton,
- tmppool));
+ SVN_ERR(ctx->update_editor->delete_entry(full_path,
+ delete_rev,
+ info->dir->dir_baton,
+ tmppool));
svn_pool_destroy(tmppool);
}
@@ -1852,7 +1951,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
info->dir->props, ctx->sess,
ctx->sess->conns[ctx->sess->cur_conn],
info->dir->url,
- info->dir->target_rev, "0",
+ ctx->target_rev, "0",
all_props,
&ctx->done_propfinds,
info->dir->pool));
@@ -2295,7 +2394,6 @@ finish_report(void *report_baton,
svn_ra_serf__xml_parser_t *parser_ctx;
const char *report_target;
svn_boolean_t closed_root;
- int status_code;
svn_stringbuf_t *buf = NULL;
apr_pool_t *iterpool = svn_pool_create(pool);
svn_error_t *err;
@@ -2325,6 +2423,7 @@ finish_report(void *report_baton,
handler = apr_pcalloc(pool, sizeof(*handler));
+ handler->handler_pool = pool;
handler->method = "REPORT";
handler->path = report->path;
handler->body_delegate = create_update_report_body;
@@ -2344,9 +2443,6 @@ finish_report(void *report_baton,
parser_ctx->end = end_report;
parser_ctx->cdata = cdata_report;
parser_ctx->done = &report->done;
- /* While we provide a location here to store the status code, we don't
- do anything with it. The error in parser_ctx->error is sufficient. */
- parser_ctx->status_code = &status_code;
handler->response_handler = svn_ra_serf__handle_xml_parser;
handler->response_baton = parser_ctx;
@@ -2788,7 +2884,7 @@ svn_ra_serf__get_file(svn_ra_session_t *
svn_ra_serf__connection_t *conn;
const char *fetch_url;
apr_hash_t *fetch_props;
- svn_node_kind_t res_kind;
+ svn_kind_t res_kind;
/* What connection should we go on? */
conn = session->conns[session->cur_conn];
@@ -2804,24 +2900,23 @@ svn_ra_serf__get_file(svn_ra_session_t *
*/
if (SVN_IS_VALID_REVNUM(revision) || fetched_rev)
{
- const char *baseline_url, *rel_path;
-
- SVN_ERR(svn_ra_serf__get_baseline_info(&baseline_url, &rel_path,
- session, conn, fetch_url,
- revision, fetched_rev, pool));
- fetch_url = svn_path_url_add_component2(baseline_url, rel_path, pool);
+ SVN_ERR(svn_ra_serf__get_stable_url(&fetch_url, fetched_rev,
+ session, conn,
+ fetch_url, revision,
+ pool, pool));
revision = SVN_INVALID_REVNUM;
}
+ /* REVISION is always SVN_INVALID_REVNUM */
+ SVN_ERR_ASSERT(!SVN_IS_VALID_REVNUM(revision));
- SVN_ERR(svn_ra_serf__retrieve_props(&fetch_props, session, conn, fetch_url,
- revision, "0",
- props ? all_props : check_path_props,
- pool, pool));
-
- /* Verify that resource type is not colelction. */
- SVN_ERR(svn_ra_serf__get_resource_type(&res_kind, fetch_props, fetch_url,
- revision));
- if (res_kind != svn_node_file)
+ SVN_ERR(svn_ra_serf__fetch_node_props(&fetch_props, conn, fetch_url,
+ SVN_INVALID_REVNUM,
+ props ? all_props : check_path_props,
+ pool, pool));
+
+ /* Verify that resource type is not collection. */
+ SVN_ERR(svn_ra_serf__get_resource_type(&res_kind, fetch_props));
+ if (res_kind != svn_kind_file)
{
return svn_error_create(SVN_ERR_FS_NOT_FILE, NULL,
_("Can't get text contents of a directory"));
@@ -2830,8 +2925,10 @@ svn_ra_serf__get_file(svn_ra_session_t *
/* TODO Filter out all of our props into a usable format. */
if (props)
{
- SVN_ERR(svn_ra_serf__flatten_props(props, fetch_props, fetch_url,
- revision, pool, pool));
+ /* ### flatten_props() does not copy PROPVALUE, but fetch_node_props()
+ ### put them into POOL, so we're okay. */
+ SVN_ERR(svn_ra_serf__flatten_props(props, fetch_props,
+ pool, pool));
}
if (stream)
@@ -2848,6 +2945,8 @@ svn_ra_serf__get_file(svn_ra_session_t *
stream_ctx->info->name = fetch_url;
handler = apr_pcalloc(pool, sizeof(*handler));
+
+ handler->handler_pool = pool;
handler->method = "GET";
handler->path = fetch_url;
handler->conn = conn;
@@ -2862,6 +2961,8 @@ svn_ra_serf__get_file(svn_ra_session_t *
handler->response_error = cancel_fetch;
handler->response_error_baton = stream_ctx;
+ stream_ctx->handler = handler;
+
svn_ra_serf__request_create(handler);
SVN_ERR(svn_ra_serf__context_run_wait(&stream_ctx->done, session, pool));