You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/16 22:32:54 UTC
svn commit: r1339349 [14/37] - in /subversion/branches/fix-rdump-editor: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/ contrib/client-side/vim/
contrib/server-side/ notes/ notes/api-errat...
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.h Wed May 16 20:32:43 2012
@@ -26,7 +26,7 @@
#include "fs.h"
/**
- * Prepend the @a number to the @a string in a space efficient way that
+ * Prepend the @a number to the @a string in a space efficient way such that
* no other (number,string) combination can produce the same result.
* Allocate temporaries as well as the result from @a pool.
*/
@@ -36,8 +36,8 @@ svn_fs_fs__combine_number_and_string(apr
apr_pool_t *pool);
/**
- * Combine the numbers @a a and @a b a space efficient way that no other
- * combination of numbers can produce the same result.
+ * Combine the numbers @a a and @a b in a space efficient way such that no
+ * other combination of numbers can produce the same result.
* Allocate temporaries as well as the result from @a pool.
*/
const char*
@@ -77,7 +77,7 @@ typedef struct
* #svn_fs_fs__txdelta_cached_window_t.
*/
svn_error_t *
-svn_fs_fs__serialize_txdelta_window(char **buffer,
+svn_fs_fs__serialize_txdelta_window(void **buffer,
apr_size_t *buffer_size,
void *item,
apr_pool_t *pool);
@@ -88,7 +88,7 @@ svn_fs_fs__serialize_txdelta_window(char
*/
svn_error_t *
svn_fs_fs__deserialize_txdelta_window(void **item,
- char *buffer,
+ void *buffer,
apr_size_t buffer_size,
apr_pool_t *pool);
@@ -97,7 +97,7 @@ svn_fs_fs__deserialize_txdelta_window(vo
* (@a in is an #apr_array_header_t of apr_off_t elements).
*/
svn_error_t *
-svn_fs_fs__serialize_manifest(char **data,
+svn_fs_fs__serialize_manifest(void **data,
apr_size_t *data_len,
void *in,
apr_pool_t *pool);
@@ -108,7 +108,7 @@ svn_fs_fs__serialize_manifest(char **dat
*/
svn_error_t *
svn_fs_fs__deserialize_manifest(void **out,
- char *data,
+ void *data,
apr_size_t data_len,
apr_pool_t *pool);
@@ -117,7 +117,7 @@ svn_fs_fs__deserialize_manifest(void **o
* (@a in is an #apr_hash_t of svn_string_t elements, keyed by const char*).
*/
svn_error_t *
-svn_fs_fs__serialize_properties(char **data,
+svn_fs_fs__serialize_properties(void **data,
apr_size_t *data_len,
void *in,
apr_pool_t *pool);
@@ -128,7 +128,7 @@ svn_fs_fs__serialize_properties(char **d
*/
svn_error_t *
svn_fs_fs__deserialize_properties(void **out,
- char *data,
+ void *data,
apr_size_t data_len,
apr_pool_t *pool);
@@ -136,7 +136,7 @@ svn_fs_fs__deserialize_properties(void *
* Implements #svn_cache__serialize_func_t for #svn_fs_id_t
*/
svn_error_t *
-svn_fs_fs__serialize_id(char **data,
+svn_fs_fs__serialize_id(void **data,
apr_size_t *data_len,
void *in,
apr_pool_t *pool);
@@ -146,7 +146,7 @@ svn_fs_fs__serialize_id(char **data,
*/
svn_error_t *
svn_fs_fs__deserialize_id(void **out,
- char *data,
+ void *data,
apr_size_t data_len,
apr_pool_t *pool);
@@ -154,7 +154,7 @@ svn_fs_fs__deserialize_id(void **out,
* Implements #svn_cache__serialize_func_t for #node_revision_t
*/
svn_error_t *
-svn_fs_fs__serialize_node_revision(char **buffer,
+svn_fs_fs__serialize_node_revision(void **buffer,
apr_size_t *buffer_size,
void *item,
apr_pool_t *pool);
@@ -164,7 +164,7 @@ svn_fs_fs__serialize_node_revision(char
*/
svn_error_t *
svn_fs_fs__deserialize_node_revision(void **item,
- char *buffer,
+ void *buffer,
apr_size_t buffer_size,
apr_pool_t *pool);
@@ -172,7 +172,7 @@ svn_fs_fs__deserialize_node_revision(voi
* Implements #svn_cache__serialize_func_t for a directory contents hash
*/
svn_error_t *
-svn_fs_fs__serialize_dir_entries(char **data,
+svn_fs_fs__serialize_dir_entries(void **data,
apr_size_t *data_len,
void *in,
apr_pool_t *pool);
@@ -182,7 +182,7 @@ svn_fs_fs__serialize_dir_entries(char **
*/
svn_error_t *
svn_fs_fs__deserialize_dir_entries(void **out,
- char *data,
+ void *data,
apr_size_t data_len,
apr_pool_t *pool);
@@ -192,7 +192,7 @@ svn_fs_fs__deserialize_dir_entries(void
* serialized manifest array @a data and @a data_len. */
svn_error_t *
svn_fs_fs__get_sharded_offset(void **out,
- const char *data,
+ const void *data,
apr_size_t data_len,
void *baton,
apr_pool_t *pool);
@@ -204,7 +204,7 @@ svn_fs_fs__get_sharded_offset(void **out
*/
svn_error_t *
svn_fs_fs__extract_dir_entry(void **out,
- const char *data,
+ const void *data,
apr_size_t data_len,
void *baton,
apr_pool_t *pool);
@@ -230,7 +230,7 @@ typedef struct replace_baton_t
* identified by its name in the #replace_baton_t in @a baton.
*/
svn_error_t *
-svn_fs_fs__replace_dir_entry(char **data,
+svn_fs_fs__replace_dir_entry(void **data,
apr_size_t *data_len,
void *baton,
apr_pool_t *pool);
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.c Wed May 16 20:32:43 2012
@@ -57,6 +57,7 @@
#include "tree.h"
#include "fs_fs.h"
#include "id.h"
+#include "temp_serializer.h"
#include "private/svn_mergeinfo_private.h"
#include "private/svn_fs_util.h"
@@ -154,8 +155,8 @@ locate_cache(svn_cache__t **cache,
{
fs_fs_data_t *ffd = root->fs->fsap_data;
if (cache) *cache = ffd->rev_node_cache;
- if (key && path) *key = apr_psprintf(pool, "%ld%s",
- root->rev, path);
+ if (key && path) *key
+ = svn_fs_fs__combine_number_and_string(root->rev, path, pool);
}
}
@@ -358,7 +359,7 @@ mutable_root_node(dag_node_t **node_p,
return svn_fs_fs__dag_clone_root(node_p, root->fs, root->txn, pool);
else
/* If it's not a transaction root, we can't change its contents. */
- return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path, pool);
+ return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path);
}
@@ -502,7 +503,7 @@ get_copy_inheritance(copy_id_inherit_t *
or if it is a branch point that we are accessing via its original
copy destination path. */
SVN_ERR(svn_fs_fs__dag_get_copyroot(©root_rev, ©root_path,
- child->node,pool));
+ child->node));
SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev, pool));
SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool));
copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
@@ -594,6 +595,7 @@ open_path(parent_path_t **parent_path_p,
const char *rest; /* The portion of PATH we haven't traversed yet. */
const char *canon_path = svn_fs__canonicalize_abspath(path, pool);
const char *path_so_far = "/";
+ apr_pool_t *iterpool = svn_pool_create(pool);
/* Make a parent_path item for the root node, using its own current
copy id. */
@@ -614,6 +616,8 @@ open_path(parent_path_t **parent_path_p,
char *entry;
dag_node_t *child;
+ svn_pool_clear(iterpool);
+
/* Parse out the next entry from the path. */
entry = svn_fs__next_entry_name(&next, rest, pool);
@@ -642,7 +646,7 @@ open_path(parent_path_t **parent_path_p,
if (cached_node)
child = cached_node;
else
- err = svn_fs_fs__dag_open(&child, here, entry, pool);
+ err = svn_fs_fs__dag_open(&child, here, entry, pool, iterpool);
/* "file not found" requires special handling. */
if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
@@ -676,14 +680,14 @@ open_path(parent_path_t **parent_path_p,
if (txn_id)
{
SVN_ERR(get_copy_inheritance(&inherit, ©_path,
- fs, parent_path, txn_id, pool));
+ fs, parent_path, txn_id, iterpool));
parent_path->copy_inherit = inherit;
parent_path->copy_src_path = apr_pstrdup(pool, copy_path);
}
/* Cache the node we found (if it wasn't already cached). */
if (! cached_node)
- SVN_ERR(dag_node_cache_set(root, path_so_far, child, pool));
+ SVN_ERR(dag_node_cache_set(root, path_so_far, child, iterpool));
}
/* Are we finished traversing the path? */
@@ -692,13 +696,14 @@ open_path(parent_path_t **parent_path_p,
/* The path isn't finished yet; we'd better be in a directory. */
if (svn_fs_fs__dag_node_kind(child) != svn_node_dir)
- SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far, pool),
- apr_psprintf(pool, _("Failure opening '%s'"), path));
+ SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far),
+ apr_psprintf(iterpool, _("Failure opening '%s'"), path));
rest = next;
here = child;
}
+ svn_pool_destroy(iterpool);
*parent_path_p = parent_path;
return SVN_NO_ERROR;
}
@@ -763,7 +768,7 @@ make_path_mutable(svn_fs_root_t *root,
/* Determine what copyroot our new child node should use. */
SVN_ERR(svn_fs_fs__dag_get_copyroot(©root_rev, ©root_path,
- parent_path->node, pool));
+ parent_path->node));
SVN_ERR(svn_fs_fs__revision_root(©root_root, root->fs,
copyroot_rev, pool));
SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool));
@@ -1072,8 +1077,7 @@ fs_change_node_prop(svn_fs_root_t *root,
{
apr_int64_t increment = 0;
svn_boolean_t had_mergeinfo;
- SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&had_mergeinfo, parent_path->node,
- pool));
+ SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&had_mergeinfo, parent_path->node));
if (value && !had_mergeinfo)
increment = 1;
@@ -1127,7 +1131,7 @@ fs_props_changed(svn_boolean_t *changed_
SVN_ERR(get_dag(&node1, root1, path1, pool));
SVN_ERR(get_dag(&node2, root2, path2, pool));
return svn_fs_fs__dag_things_different(changed_p, NULL,
- node1, node2, pool);
+ node1, node2);
}
@@ -1142,30 +1146,6 @@ get_root(dag_node_t **node, svn_fs_root_
}
-static svn_error_t *
-update_ancestry(svn_fs_t *fs,
- const svn_fs_id_t *source_id,
- const svn_fs_id_t *target_id,
- const char *target_path,
- int source_pred_count,
- apr_pool_t *pool)
-{
- node_revision_t *noderev;
-
- if (svn_fs_fs__id_txn_id(target_id) == NULL)
- return svn_error_createf
- (SVN_ERR_FS_NOT_MUTABLE, NULL,
- _("Unexpected immutable node at '%s'"), target_path);
-
- SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, target_id, pool));
- noderev->predecessor_id = source_id;
- noderev->predecessor_count = source_pred_count;
- if (noderev->predecessor_count != -1)
- noderev->predecessor_count++;
- return svn_fs_fs__put_node_revision(fs, target_id, noderev, FALSE, pool);
-}
-
-
/* Set the contents of CONFLICT_PATH to PATH, and return an
SVN_ERR_FS_CONFLICT error that indicates that there was a conflict
at PATH. Perform all allocations in POOL (except the allocation of
@@ -1217,8 +1197,8 @@ merge(svn_stringbuf_t *conflict_p,
apr_hash_index_t *hi;
svn_fs_t *fs;
apr_pool_t *iterpool;
- int pred_count;
apr_int64_t mergeinfo_increment = 0;
+ svn_boolean_t fs_supports_mergeinfo;
/* Make sure everyone comes from the same filesystem. */
fs = svn_fs_fs__dag_get_fs(ancestor);
@@ -1362,9 +1342,11 @@ merge(svn_stringbuf_t *conflict_p,
/* ### todo: it would be more efficient to simply check for a NULL
entries hash where necessary below than to allocate an empty hash
here, but another day, another day... */
- SVN_ERR(svn_fs_fs__dag_dir_entries(&s_entries, source, pool, pool));
- SVN_ERR(svn_fs_fs__dag_dir_entries(&t_entries, target, pool, pool));
- SVN_ERR(svn_fs_fs__dag_dir_entries(&a_entries, ancestor, pool, pool));
+ SVN_ERR(svn_fs_fs__dag_dir_entries(&s_entries, source, pool));
+ SVN_ERR(svn_fs_fs__dag_dir_entries(&t_entries, target, pool));
+ SVN_ERR(svn_fs_fs__dag_dir_entries(&a_entries, ancestor, pool));
+
+ fs_supports_mergeinfo = svn_fs_fs__fs_supports_mergeinfo(fs);
/* for each entry E in a_entries... */
iterpool = svn_pool_create(pool);
@@ -1397,12 +1379,11 @@ merge(svn_stringbuf_t *conflict_p,
dag_node_t *t_ent_node;
SVN_ERR(svn_fs_fs__dag_get_node(&t_ent_node, fs,
t_entry->id, iterpool));
- if (svn_fs_fs__fs_supports_mergeinfo(fs))
+ if (fs_supports_mergeinfo)
{
apr_int64_t mergeinfo_start;
SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start,
- t_ent_node,
- iterpool));
+ t_ent_node));
mergeinfo_increment -= mergeinfo_start;
}
@@ -1412,12 +1393,11 @@ merge(svn_stringbuf_t *conflict_p,
SVN_ERR(svn_fs_fs__dag_get_node(&s_ent_node, fs,
s_entry->id, iterpool));
- if (svn_fs_fs__fs_supports_mergeinfo(fs))
+ if (fs_supports_mergeinfo)
{
apr_int64_t mergeinfo_end;
SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end,
- s_ent_node,
- iterpool));
+ s_ent_node));
mergeinfo_increment += mergeinfo_end;
}
@@ -1490,7 +1470,7 @@ merge(svn_stringbuf_t *conflict_p,
txn_id,
&sub_mergeinfo_increment,
iterpool));
- if (svn_fs_fs__fs_supports_mergeinfo(fs))
+ if (fs_supports_mergeinfo)
mergeinfo_increment += sub_mergeinfo_increment;
}
@@ -1526,12 +1506,11 @@ merge(svn_stringbuf_t *conflict_p,
SVN_ERR(svn_fs_fs__dag_get_node(&s_ent_node, fs,
s_entry->id, iterpool));
- if (svn_fs_fs__fs_supports_mergeinfo(fs))
+ if (fs_supports_mergeinfo)
{
apr_int64_t mergeinfo_s;
SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_s,
- s_ent_node,
- iterpool));
+ s_ent_node));
mergeinfo_increment += mergeinfo_s;
}
@@ -1541,11 +1520,9 @@ merge(svn_stringbuf_t *conflict_p,
}
svn_pool_destroy(iterpool);
- SVN_ERR(svn_fs_fs__dag_get_predecessor_count(&pred_count, source, pool));
- SVN_ERR(update_ancestry(fs, source_id, target_id, target_path,
- pred_count, pool));
+ SVN_ERR(svn_fs_fs__dag_update_ancestry(target, source, pool));
- if (svn_fs_fs__fs_supports_mergeinfo(fs))
+ if (fs_supports_mergeinfo)
SVN_ERR(svn_fs_fs__dag_increment_mergeinfo_count(target,
mergeinfo_increment,
pool));
@@ -1830,7 +1807,7 @@ fs_dir_entries(apr_hash_t **table_p,
/* Get the entries for this path in the caller's pool. */
SVN_ERR(get_dag(&node, root, path, pool));
- return svn_fs_fs__dag_dir_entries(table_p, node, pool, pool);
+ return svn_fs_fs__dag_dir_entries(table_p, node, pool);
}
@@ -1860,7 +1837,7 @@ fs_make_dir(svn_fs_root_t *root,
/* If there's already a sub-directory by that name, complain. This
also catches the case of trying to make a subdirectory named `/'. */
if (parent_path->node)
- return SVN_FS__ALREADY_EXISTS(root, path, pool);
+ return SVN_FS__ALREADY_EXISTS(root, path);
/* Create the subdirectory. */
SVN_ERR(make_path_mutable(root, parent_path->parent, path, pool));
@@ -1916,8 +1893,7 @@ fs_delete_node(svn_fs_root_t *root,
SVN_ERR(make_path_mutable(root, parent_path->parent, path, pool));
if (svn_fs_fs__fs_supports_mergeinfo(root->fs))
SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_count,
- parent_path->node,
- pool));
+ parent_path->node));
SVN_ERR(svn_fs_fs__dag_delete(parent_path->parent->node,
parent_path->entry,
txn_id, pool));
@@ -1949,17 +1925,7 @@ fs_same_p(svn_boolean_t *same_p,
svn_fs_t *fs2,
apr_pool_t *pool)
{
- const char *uuid1;
- const char *uuid2;
-
- /* Random thought: if fetching UUIDs to compare filesystems is too
- expensive, one solution would be to cache the UUID in each fs
- object (copying the UUID into fs->pool, of course). */
-
- SVN_ERR(fs1->vtable->get_uuid(fs1, &uuid1, pool));
- SVN_ERR(fs2->vtable->get_uuid(fs2, &uuid2, pool));
-
- *same_p = ! strcmp(uuid1, uuid2);
+ *same_p = ! strcmp(fs1->uuid, fs2->uuid);
return SVN_NO_ERROR;
}
@@ -2032,8 +1998,7 @@ copy_helper(svn_fs_root_t *from_root,
kind = svn_fs_path_change_replace;
if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs))
SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start,
- to_parent_path->node,
- pool));
+ to_parent_path->node));
}
else
{
@@ -2043,7 +2008,7 @@ copy_helper(svn_fs_root_t *from_root,
if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs))
SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end,
- from_node, pool));
+ from_node));
/* Make sure the target node's parents are mutable. */
SVN_ERR(make_path_mutable(to_root, to_parent_path->parent,
@@ -2176,8 +2141,8 @@ fs_copied_from(svn_revnum_t *rev_p,
/* There is no cached entry, look it up the old-fashioned
way. */
SVN_ERR(get_dag(&node, root, path, pool));
- SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(©from_rev, node, pool));
- SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©from_path, node, pool));
+ SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(©from_rev, node));
+ SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©from_path, node));
}
*rev_p = copyfrom_rev;
@@ -2207,7 +2172,7 @@ fs_make_file(svn_fs_root_t *root,
/* If there's already a file by that name, complain.
This also catches the case of trying to make a file named `/'. */
if (parent_path->node)
- return SVN_FS__ALREADY_EXISTS(root, path, pool);
+ return SVN_FS__ALREADY_EXISTS(root, path);
/* Check (non-recursively) to see if path is locked; if so, check
that we can use it. */
@@ -2493,17 +2458,8 @@ fs_apply_textdelta(svn_txdelta_window_ha
tb->root = root;
tb->path = path;
tb->pool = pool;
-
- if (base_checksum)
- tb->base_checksum = svn_checksum_dup(base_checksum, pool);
- else
- tb->base_checksum = NULL;
-
- if (result_checksum)
- tb->result_checksum = svn_checksum_dup(result_checksum, pool);
- else
- tb->result_checksum = NULL;
-
+ tb->base_checksum = svn_checksum_dup(base_checksum, pool);
+ tb->result_checksum = svn_checksum_dup(result_checksum, pool);
SVN_ERR(apply_textdelta(tb, pool));
@@ -2635,11 +2591,7 @@ fs_apply_text(svn_stream_t **contents_p,
tb->root = root;
tb->path = path;
tb->pool = pool;
-
- if (result_checksum)
- tb->result_checksum = svn_checksum_dup(result_checksum, pool);
- else
- tb->result_checksum = NULL;
+ tb->result_checksum = svn_checksum_dup(result_checksum, pool);
SVN_ERR(apply_text(tb, pool));
@@ -2687,7 +2639,7 @@ fs_contents_changed(svn_boolean_t *chang
SVN_ERR(get_dag(&node1, root1, path1, pool));
SVN_ERR(get_dag(&node2, root2, path2, pool));
return svn_fs_fs__dag_things_different(NULL, changed_p,
- node1, node2, pool);
+ node1, node2);
}
@@ -2819,7 +2771,7 @@ find_youngest_copyroot(svn_revnum_t *rev
/* Find our copyroot. */
SVN_ERR(svn_fs_fs__dag_get_copyroot(&rev_mine, &path_mine,
- parent_path->node, pool));
+ parent_path->node));
/* If a parent and child were copied to in the same revision, prefer
the child copy target, since it is the copy relevant to the
@@ -2899,7 +2851,7 @@ static svn_error_t *fs_closest_copy(svn_
if (created_rev == copy_dst_rev)
{
const svn_fs_id_t *pred;
- SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred, copy_dst_node, pool));
+ SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred, copy_dst_node));
if (! pred)
return SVN_NO_ERROR;
}
@@ -3060,7 +3012,7 @@ fs_node_origin_rev(svn_revnum_t *revisio
value cached in the node (which is allocated in
SUBPOOL... maybe). */
svn_pool_clear(predidpool);
- SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node, subpool));
+ SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node));
pred_id = pred_id ? svn_fs_fs__id_copy(pred_id, predidpool) : NULL;
}
while (pred_id);
@@ -3162,7 +3114,7 @@ history_prev(void *baton, apr_pool_t *po
no predecessor, in which case we're all done!). */
const svn_fs_id_t *pred_id;
- SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node, pool));
+ SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node));
if (! pred_id)
return SVN_NO_ERROR;
@@ -3210,8 +3162,8 @@ history_prev(void *baton, apr_pool_t *po
/* If we get here, then our current path is the destination
of, or the child of the destination of, a copy. Fill
in the return values and get outta here. */
- SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&src_rev, node, pool));
- SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©_src, node, pool));
+ SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&src_rev, node));
+ SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(©_src, node));
dst_rev = copyroot_rev;
src_path = svn_fspath__join(copy_src, remainder_path, pool);
@@ -3375,7 +3327,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, dir_dag,
- scratch_pool, scratch_pool));
+ scratch_pool));
for (hi = apr_hash_first(scratch_pool, entries);
hi;
@@ -3391,9 +3343,8 @@ crawl_directory_dag_for_mergeinfo(svn_fs
kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
- SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag, iterpool));
- SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag,
- iterpool));
+ SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag));
+ SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag));
if (has_mergeinfo)
{
@@ -3468,7 +3419,6 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
parent_path_t *parent_path, *nearest_ancestor;
apr_hash_t *proplist;
svn_string_t *mergeinfo_string;
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
*mergeinfo = NULL;
@@ -3488,17 +3438,14 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
{
svn_boolean_t has_mergeinfo;
- svn_pool_clear(iterpool);
-
SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo,
- nearest_ancestor->node, iterpool));
+ nearest_ancestor->node));
if (has_mergeinfo)
break;
/* No need to loop if we're looking for explicit mergeinfo. */
if (inherit == svn_mergeinfo_explicit)
{
- svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -3507,13 +3454,10 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
/* Run out? There's no mergeinfo. */
if (!nearest_ancestor)
{
- svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
}
- svn_pool_destroy(iterpool);
-
SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, nearest_ancestor->node,
scratch_pool));
mergeinfo_string = apr_hash_get(proplist, SVN_PROP_MERGEINFO,
@@ -3581,8 +3525,7 @@ add_descendant_mergeinfo(svn_mergeinfo_c
SVN_ERR(get_dag(&this_dag, root, path, scratch_pool));
SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down,
- this_dag,
- scratch_pool));
+ this_dag));
if (go_down)
SVN_ERR(crawl_directory_dag_for_mergeinfo(root,
path,
@@ -3783,7 +3726,8 @@ make_txn_root(svn_fs_root_t **root_p,
svn_fs_fs__dag_deserialize,
APR_HASH_KEY_STRING,
32, 20, FALSE,
- apr_pstrcat(pool, txn, ":TXN", (char *)NULL),
+ apr_pstrcat(pool, txn, ":TXN",
+ (char *)NULL),
root->pool));
/* Initialize transaction-local caches in FS.
@@ -3797,3 +3741,170 @@ make_txn_root(svn_fs_root_t **root_p,
*root_p = root;
return SVN_NO_ERROR;
}
+
+
+
+/* Verify. */
+static APR_INLINE const char *
+stringify_node(dag_node_t *node,
+ apr_pool_t *pool)
+{
+ /* ### TODO: print some PATH@REV to it, too. */
+ return svn_fs_fs__id_unparse(svn_fs_fs__dag_get_id(node), pool)->data;
+}
+
+/* Check metadata sanity on NODE, and on its children. Manually verify
+ information for DAG nodes in revision REV, and trust the metadata
+ accuracy for nodes belonging to older revisions. */
+static svn_error_t *
+verify_node(dag_node_t *node,
+ svn_revnum_t rev,
+ apr_pool_t *pool)
+{
+ svn_boolean_t has_mergeinfo;
+ apr_int64_t mergeinfo_count;
+ const svn_fs_id_t *pred_id;
+ svn_fs_t *fs = svn_fs_fs__dag_get_fs(node);
+ int pred_count;
+ svn_node_kind_t kind;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ /* Fetch some data. */
+ SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, node));
+ SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_count, node));
+ SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node));
+ SVN_ERR(svn_fs_fs__dag_get_predecessor_count(&pred_count, node));
+ kind = svn_fs_fs__dag_node_kind(node);
+
+ /* Sanity check. */
+ if (mergeinfo_count < 0)
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ "Negative mergeinfo-count %" APR_INT64_T_FMT
+ " on node '%s'",
+ mergeinfo_count, stringify_node(node, iterpool));
+
+ /* Issue #4129. (This check will explicitly catch non-root instances too.) */
+ if (pred_id)
+ {
+ dag_node_t *pred;
+ int pred_pred_count;
+ SVN_ERR(svn_fs_fs__dag_get_node(&pred, fs, pred_id, iterpool));
+ SVN_ERR(svn_fs_fs__dag_get_predecessor_count(&pred_pred_count, pred));
+ if (pred_pred_count+1 != pred_count)
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ "Predecessor count mismatch: "
+ "%s has %d, but %s has %d",
+ stringify_node(node, iterpool), pred_count,
+ stringify_node(pred, iterpool),
+ pred_pred_count);
+ }
+
+ /* Kind-dependent verifications. */
+ if (kind == svn_node_none)
+ {
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ "Node '%s' has kind 'none'",
+ stringify_node(node, iterpool));
+ }
+ if (kind == svn_node_file)
+ {
+ if (has_mergeinfo != mergeinfo_count) /* comparing int to bool */
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ "File node '%s' has inconsistent mergeinfo: "
+ "has_mergeinfo=%d, "
+ "mergeinfo_count=%" APR_INT64_T_FMT,
+ stringify_node(node, iterpool),
+ has_mergeinfo, mergeinfo_count);
+ }
+ if (kind == svn_node_dir)
+ {
+ apr_hash_t *entries;
+ apr_hash_index_t *hi;
+ apr_int64_t children_mergeinfo = 0;
+
+ SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, node, pool));
+
+ /* Compute CHILDREN_MERGEINFO. */
+ for (hi = apr_hash_first(pool, entries);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ svn_fs_dirent_t *dirent = svn__apr_hash_index_val(hi);
+ dag_node_t *child;
+ svn_revnum_t child_rev;
+ apr_int64_t child_mergeinfo;
+
+ svn_pool_clear(iterpool);
+
+ /* Compute CHILD_REV. */
+ SVN_ERR(svn_fs_fs__dag_get_node(&child, fs, dirent->id, iterpool));
+ SVN_ERR(svn_fs_fs__dag_get_revision(&child_rev, child, iterpool));
+
+ if (child_rev == rev)
+ SVN_ERR(verify_node(child, rev, iterpool));
+
+ SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&child_mergeinfo, child));
+ children_mergeinfo += child_mergeinfo;
+ }
+
+ /* Side-effect of issue #4129. */
+ if (children_mergeinfo+has_mergeinfo != mergeinfo_count)
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ "Mergeinfo-count discrepancy on '%s': "
+ "expected %" APR_INT64_T_FMT "+%d, "
+ "counted %" APR_INT64_T_FMT,
+ stringify_node(node, iterpool),
+ mergeinfo_count, has_mergeinfo,
+ children_mergeinfo);
+ }
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__verify_root(svn_fs_root_t *root,
+ apr_pool_t *pool)
+{
+ fs_rev_root_data_t *frd;
+
+ if (root->is_txn_root)
+ /* ### Not implemented */
+ return SVN_NO_ERROR;
+ frd = root->fsap_data;
+
+ /* Recursively verify ROOT_DIR. */
+ SVN_ERR(verify_node(frd->root_dir, root->rev, pool));
+
+ /* Verify explicitly the predecessor of the root. */
+ {
+ const svn_fs_id_t *pred_id;
+ dag_node_t *pred;
+ svn_revnum_t pred_rev;
+
+ /* Only r0 should have no predecessor. */
+ SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, frd->root_dir));
+ if (!!pred_id != !!root->rev)
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ "r%ld's root node's predecessor is "
+ "unexpectedly '%s'",
+ root->rev,
+ (pred_id
+ ? svn_fs_fs__id_unparse(pred_id, pool)->data
+ : "(null)"));
+
+ /* Check the predecessor's revision. */
+ if (pred_id)
+ {
+ SVN_ERR(svn_fs_fs__dag_get_node(&pred, root->fs, pred_id, pool));
+ SVN_ERR(svn_fs_fs__dag_get_revision(&pred_rev, pred, pool));
+ if (pred_rev+1 != root->rev)
+ /* Issue #4129. */
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ "r%ld's root node's predecessor is r%ld",
+ root->rev, pred_rev);
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/tree.h Wed May 16 20:32:43 2012
@@ -78,6 +78,12 @@ svn_fs_fs__node_created_rev(svn_revnum_t
const char *path,
apr_pool_t *pool);
+/* Verify metadata for ROOT.
+ ### Currently only implemented for revision roots. */
+svn_error_t *
+svn_fs_fs__verify_root(svn_fs_root_t *root,
+ apr_pool_t *pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra/compat.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra/compat.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra/compat.c Wed May 16 20:32:43 2012
@@ -141,7 +141,7 @@ prev_log_path(const char **prev_path_p,
svn_sort__item_t item = APR_ARRAY_IDX(paths,
i - 1, svn_sort__item_t);
const char *ch_path = item.key;
- int len = strlen(ch_path);
+ size_t len = strlen(ch_path);
/* See if our path is the child of this change path. If
not, keep looking. */
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra/debug_reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra/debug_reporter.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra/debug_reporter.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra/debug_reporter.c Wed May 16 20:32:43 2012
@@ -95,7 +95,7 @@ finish_report(void *report_baton,
apr_pool_t *pool)
{
struct report_baton *rb = report_baton;
- SVN_ERR(svn_stream_printf(rb->out, pool, "finish_report()\n"));
+ SVN_ERR(svn_stream_puts(rb->out, "finish_report()\n"));
SVN_ERR(rb->wrapped_reporter->finish_report(rb->wrapped_report_baton, pool));
return SVN_NO_ERROR;
}
@@ -105,7 +105,7 @@ abort_report(void *report_baton,
apr_pool_t *pool)
{
struct report_baton *rb = report_baton;
- SVN_ERR(svn_stream_printf(rb->out, pool, "abort_report()\n"));
+ SVN_ERR(svn_stream_puts(rb->out, "abort_report()\n"));
SVN_ERR(rb->wrapped_reporter->abort_report(rb->wrapped_report_baton, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.c Wed May 16 20:32:43 2012
@@ -706,6 +706,39 @@ commit_callback_wrapper(const svn_commit
return ccwb->original_callback(ci, ccwb->original_baton, pool);
}
+
+/* Some RA layers do not correctly fill in REPOS_ROOT in commit_info, or
+ they are third-party layers conforming to an older commit_info structure.
+ Interpose a utility function to ensure the field is valid. */
+static void
+remap_commit_callback(svn_commit_callback2_t *callback,
+ void **callback_baton,
+ svn_ra_session_t *session,
+ svn_commit_callback2_t original_callback,
+ void *original_baton,
+ apr_pool_t *result_pool)
+{
+ if (original_callback == NULL)
+ {
+ *callback = NULL;
+ *callback_baton = NULL;
+ }
+ else
+ {
+ /* Allocate this in RESULT_POOL, since the callback will be called
+ long after this function has returned. */
+ struct ccw_baton *ccwb = apr_palloc(result_pool, sizeof(*ccwb));
+
+ ccwb->session = session;
+ ccwb->original_callback = original_callback;
+ ccwb->original_baton = original_baton;
+
+ *callback = commit_callback_wrapper;
+ *callback_baton = ccwb;
+ }
+}
+
+
svn_error_t *svn_ra_get_commit_editor3(svn_ra_session_t *session,
const svn_delta_editor_t **editor,
void **edit_baton,
@@ -716,20 +749,13 @@ svn_error_t *svn_ra_get_commit_editor3(s
svn_boolean_t keep_locks,
apr_pool_t *pool)
{
- /* Allocate this in a pool, since the callback will be called long after
- this function as returned. */
- struct ccw_baton *ccwb = apr_palloc(pool, sizeof(*ccwb));
-
- ccwb->original_callback = callback;
- ccwb->original_baton = callback_baton;
- ccwb->session = session;
+ remap_commit_callback(&callback, &callback_baton,
+ session, callback, callback_baton,
+ pool);
return session->vtable->get_commit_editor(session, editor, edit_baton,
revprop_table,
- callback
- ? commit_callback_wrapper
- : NULL,
- callback ? ccwb : NULL,
+ callback, callback_baton,
lock_tokens, keep_locks, pool);
}
@@ -876,6 +902,8 @@ svn_error_t *svn_ra_do_diff3(svn_ra_sess
void *diff_baton,
apr_pool_t *pool)
{
+ SVN_ERR_ASSERT(svn_path_is_empty(diff_target)
+ || svn_path_is_single_path_component(diff_target));
return session->vtable->do_diff(session,
reporter, report_baton,
revision, diff_target,
@@ -1241,6 +1269,67 @@ svn_ra_get_deleted_rev(svn_ra_session_t
return err;
}
+
+svn_error_t *
+svn_ra__get_commit_ev2(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (session->vtable->get_commit_ev2 == NULL)
+ {
+ /* The specific RA layer does not have an implementation. Use our
+ default shim over the normal commit editor. */
+
+ /* Remap for RA layers exposing Ev1. */
+ remap_commit_callback(&callback, &callback_baton,
+ session, callback, callback_baton,
+ result_pool);
+
+ return svn_error_trace(svn_ra__use_commit_shim(
+ editor,
+ session,
+ revprop_table,
+ callback, callback_baton,
+ lock_tokens,
+ keep_locks,
+ provide_base_cb,
+ provide_props_cb,
+ get_copysrc_kind_cb,
+ cb_baton,
+ cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+ }
+
+ /* Note: no need to remap the callback for Ev2. RA layers providing this
+ vtable entry should completely fill in commit_info. */
+
+ return svn_error_trace(session->vtable->get_commit_ev2(
+ editor,
+ session,
+ revprop_table,
+ callback, callback_baton,
+ lock_tokens,
+ keep_locks,
+ provide_base_cb,
+ provide_props_cb,
+ get_copysrc_kind_cb,
+ cb_baton,
+ cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+}
+
svn_error_t *
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra/ra_loader.h Wed May 16 20:32:43 2012
@@ -32,6 +32,8 @@
#include "svn_ra.h"
+#include "private/svn_ra_private.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -293,9 +295,29 @@ typedef struct svn_ra__vtable_t {
svn_revnum_t end_revision,
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+
+ /* See svn_ra__register_editor_shim_callbacks() */
svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
svn_delta_shim_callbacks_t *callbacks);
+ /* See svn_ra__get_commit_ev2() */
+ svn_error_t *(*get_commit_ev2)(
+ svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
} svn_ra__vtable_t;
/* The RA session object. */
@@ -453,6 +475,29 @@ svn_ra__get_deleted_rev_from_log(svn_ra_
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+
+/* Utility function to provide a shim between a returned Ev2 and an RA
+ provider's Ev1-based commit editor.
+
+ See svn_ra__get_commit_ev2() for parameter semantics. */
+svn_error_t *
+svn_ra__use_commit_shim(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
#ifdef __cplusplus
}
#endif
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_local/ra_plugin.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_local/ra_plugin.c Wed May 16 20:32:43 2012
@@ -76,8 +76,6 @@ get_username(svn_ra_session_t *session,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sess = session->priv;
- svn_auth_iterstate_t *iterstate;
- svn_fs_access_t *access_ctx;
/* If we've already found the username don't ask for it again. */
if (! sess->username)
@@ -88,6 +86,8 @@ get_username(svn_ra_session_t *session,
{
void *creds;
svn_auth_cred_username_t *username_creds;
+ svn_auth_iterstate_t *iterstate;
+
SVN_ERR(svn_auth_first_credentials(&creds, &iterstate,
SVN_AUTH_CRED_USERNAME,
sess->uuid, /* realmstring */
@@ -118,6 +118,8 @@ get_username(svn_ra_session_t *session,
*/
if (*sess->username)
{
+ svn_fs_access_t *access_ctx;
+
SVN_ERR(svn_fs_create_access(&access_ctx, sess->username,
session->pool));
SVN_ERR(svn_fs_set_access(sess->fs, access_ctx));
@@ -367,11 +369,12 @@ struct deltify_etc_baton
{
svn_fs_t *fs; /* the fs to deltify in */
svn_repos_t *repos; /* repos for unlocking */
- const char *fs_path; /* fs-path part of split session URL */
+ const char *fspath_base; /* fs-path part of split session URL */
+
apr_hash_t *lock_tokens; /* tokens to unlock, if any */
- apr_pool_t *pool; /* pool for scratch work */
- svn_commit_callback2_t callback; /* the original callback */
- void *callback_baton; /* the original callback's baton */
+
+ svn_commit_callback2_t commit_cb; /* the original callback */
+ void *commit_baton; /* the original callback's baton */
};
/* This implements 'svn_commit_callback_t'. Its invokes the original
@@ -380,60 +383,107 @@ struct deltify_etc_baton
BATON is 'struct deltify_etc_baton *'. */
static svn_error_t *
deltify_etc(const svn_commit_info_t *commit_info,
- void *baton, apr_pool_t *pool)
+ void *baton,
+ apr_pool_t *scratch_pool)
{
- struct deltify_etc_baton *db = baton;
+ struct deltify_etc_baton *deb = baton;
svn_error_t *err1 = SVN_NO_ERROR;
svn_error_t *err2;
- apr_hash_index_t *hi;
- apr_pool_t *iterpool;
/* Invoke the original callback first, in case someone's waiting to
know the revision number so they can go off and annotate an
issue or something. */
- if (db->callback)
- err1 = db->callback(commit_info, db->callback_baton, pool);
+ if (deb->commit_cb)
+ err1 = deb->commit_cb(commit_info, deb->commit_baton, scratch_pool);
/* Maybe unlock the paths. */
- if (db->lock_tokens)
+ if (deb->lock_tokens)
{
- iterpool = svn_pool_create(db->pool);
- for (hi = apr_hash_first(db->pool, db->lock_tokens); hi;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, deb->lock_tokens); hi;
hi = apr_hash_next(hi))
{
- const void *rel_path;
- void *val;
- const char *abs_path, *token;
+ const void *relpath = svn__apr_hash_index_key(hi);
+ const char *token = svn__apr_hash_index_val(hi);
+ const char *fspath;
svn_pool_clear(iterpool);
- apr_hash_this(hi, &rel_path, NULL, &val);
- token = val;
- abs_path = svn_fspath__join(db->fs_path, rel_path, iterpool);
+
+ fspath = svn_fspath__join(deb->fspath_base, relpath, iterpool);
+
/* We may get errors here if the lock was broken or stolen
after the commit succeeded. This is fine and should be
ignored. */
- svn_error_clear(svn_repos_fs_unlock(db->repos, abs_path, token,
+ svn_error_clear(svn_repos_fs_unlock(deb->repos, fspath, token,
FALSE, iterpool));
}
+
svn_pool_destroy(iterpool);
}
/* But, deltification shouldn't be stopped just because someone's
random callback failed, so proceed unconditionally on to
deltification. */
- err2 = svn_fs_deltify_revision(db->fs, commit_info->revision, db->pool);
+ err2 = svn_fs_deltify_revision(deb->fs, commit_info->revision, scratch_pool);
+
+ return svn_error_compose_create(err1, err2);
+}
+
- /* It's more interesting if the original callback failed, so let
- that one dominate. */
- if (err1)
+/* If LOCK_TOKENS is not NULL, then copy all tokens into the access context
+ of FS. The tokens' paths will be prepended with FSPATH_BASE.
+
+ ACCESS_POOL must match (or exceed) the lifetime of the access context
+ that was associated with FS. Typically, this is the session pool.
+
+ Temporary allocations are made in SCRATCH_POOL. */
+static svn_error_t *
+apply_lock_tokens(svn_fs_t *fs,
+ const char *fspath_base,
+ apr_hash_t *lock_tokens,
+ apr_pool_t *access_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (lock_tokens)
{
- svn_error_clear(err2);
- return err1;
+ svn_fs_access_t *access_ctx;
+
+ SVN_ERR(svn_fs_get_access(&access_ctx, fs));
+
+ /* If there is no access context, the filesystem will scream if a
+ lock is needed. */
+ if (access_ctx)
+ {
+ apr_hash_index_t *hi;
+
+ /* Note: we have no use for an iterpool here since the data
+ within the loop is copied into ACCESS_POOL. */
+
+ for (hi = apr_hash_first(scratch_pool, lock_tokens); hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *relpath = svn__apr_hash_index_key(hi);
+ const char *token = svn__apr_hash_index_val(hi);
+ const char *fspath;
+
+ /* The path needs to live as long as ACCESS_CTX. */
+ fspath = svn_fspath__join(fspath_base, relpath, access_pool);
+
+ /* The token must live as long as ACCESS_CTX. */
+ token = apr_pstrdup(access_pool, token);
+
+ SVN_ERR(svn_fs_access_add_lock_token2(access_ctx, fspath,
+ token));
+ }
+ }
}
- return err2;
+ return SVN_NO_ERROR;
}
+
/*----------------------------------------------------------------*/
/*** The RA vtable routines ***/
@@ -679,47 +729,24 @@ svn_ra_local__get_commit_editor(svn_ra_s
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sess = session->priv;
- struct deltify_etc_baton *db = apr_palloc(pool, sizeof(*db));
- apr_hash_index_t *hi;
- svn_fs_access_t *fs_access;
+ struct deltify_etc_baton *deb = apr_palloc(pool, sizeof(*deb));
- db->fs = sess->fs;
- db->repos = sess->repos;
- db->fs_path = sess->fs_path->data;
+ /* Prepare the baton for deltify_etc() */
+ deb->fs = sess->fs;
+ deb->repos = sess->repos;
+ deb->fspath_base = sess->fs_path->data;
if (! keep_locks)
- db->lock_tokens = lock_tokens;
+ deb->lock_tokens = lock_tokens;
else
- db->lock_tokens = NULL;
- db->pool = pool;
- db->callback = callback;
- db->callback_baton = callback_baton;
+ deb->lock_tokens = NULL;
+ deb->commit_cb = callback;
+ deb->commit_baton = callback_baton;
SVN_ERR(get_username(session, pool));
/* If there are lock tokens to add, do so. */
- if (lock_tokens)
- {
- SVN_ERR(svn_fs_get_access(&fs_access, sess->fs));
-
- /* If there is no access context, the filesystem will scream if a
- lock is needed. */
- if (fs_access)
- {
- for (hi = apr_hash_first(pool, lock_tokens); hi;
- hi = apr_hash_next(hi))
- {
- void *val;
- const char *abs_path, *token;
- const void *key;
-
- apr_hash_this(hi, &key, NULL, &val);
- abs_path = svn_fspath__join(sess->fs_path->data, key, pool);
- token = val;
- SVN_ERR(svn_fs_access_add_lock_token2(fs_access,
- abs_path, token));
- }
- }
- }
+ SVN_ERR(apply_lock_tokens(sess->fs, sess->fs_path->data, lock_tokens,
+ session->pool, pool));
/* Copy the revprops table so we can add the username. */
revprop_table = apr_hash_copy(pool, revprop_table);
@@ -730,7 +757,7 @@ svn_ra_local__get_commit_editor(svn_ra_s
return svn_repos_get_commit_editor5
(editor, edit_baton, sess->repos, NULL,
svn_path_uri_decode(sess->repos_url, pool), sess->fs_path->data,
- revprop_table, deltify_etc, db, NULL, NULL, pool);
+ revprop_table, deltify_etc, deb, NULL, NULL, pool);
}
@@ -1514,6 +1541,62 @@ svn_ra_local__register_editor_shim_callb
return SVN_NO_ERROR;
}
+
+static svn_error_t *
+svn_ra_local__get_commit_ev2(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprops,
+ svn_commit_callback2_t commit_cb,
+ void *commit_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_local__session_baton_t *sess = session->priv;
+ struct deltify_etc_baton *deb = apr_palloc(result_pool, sizeof(*deb));
+
+ /* NOTE: the RA callbacks are ignored. We pass everything directly to
+ the REPOS editor. */
+
+ /* Prepare the baton for deltify_etc() */
+ deb->fs = sess->fs;
+ deb->repos = sess->repos;
+ deb->fspath_base = sess->fs_path->data;
+ if (! keep_locks)
+ deb->lock_tokens = lock_tokens;
+ else
+ deb->lock_tokens = NULL;
+ deb->commit_cb = commit_cb;
+ deb->commit_baton = commit_baton;
+
+ /* Ensure there is a username (and an FS access context) associated with
+ the session and its FS handle. */
+ SVN_ERR(get_username(session, scratch_pool));
+
+ /* If there are lock tokens to add, do so. */
+ SVN_ERR(apply_lock_tokens(sess->fs, sess->fs_path->data, lock_tokens,
+ session->pool, scratch_pool));
+
+ /* Copy the REVPROPS and insert the author/username. */
+ revprops = apr_hash_copy(scratch_pool, revprops);
+ apr_hash_set(revprops, SVN_PROP_REVISION_AUTHOR, APR_HASH_KEY_STRING,
+ svn_string_create(sess->username, scratch_pool));
+
+ return svn_error_trace(svn_repos__get_commit_ev2(
+ editor, sess->repos, NULL /* authz */,
+ NULL /* authz_repos_name */, NULL /* authz_user */,
+ revprops,
+ deltify_etc, deb, cancel_func, cancel_baton,
+ result_pool, scratch_pool));
+}
+
/*----------------------------------------------------------------*/
static const svn_version_t *
@@ -1561,7 +1644,8 @@ static const svn_ra__vtable_t ra_local_v
svn_ra_local__has_capability,
svn_ra_local__replay_range,
svn_ra_local__get_deleted_rev,
- svn_ra_local__register_editor_shim_callbacks
+ svn_ra_local__register_editor_shim_callbacks,
+ svn_ra_local__get_commit_ev2
};
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/commit.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/commit.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/commit.c Wed May 16 20:32:43 2012
@@ -737,6 +737,7 @@ static svn_error_t * commit_open_root(vo
transaction (and, optionally, a corresponding activity). */
svn_ra_neon__request_t *req;
const char *header_val;
+ svn_error_t *err;
SVN_ERR(svn_ra_neon__request_create(&req, cc->ras, "POST",
cc->ras->me_resource, dir_pool));
@@ -749,33 +750,39 @@ static svn_error_t * commit_open_root(vo
svn_uuid_generate(dir_pool));
#endif
- SVN_ERR(svn_ra_neon__request_dispatch(NULL, req, NULL, "( create-txn )",
- 201, 0, dir_pool));
-
- /* Check the response headers for either the virtual transaction
- details, or the real transaction details. We need to have
- one or the other of those! */
- if ((header_val = ne_get_response_header(req->ne_req,
- SVN_DAV_VTXN_NAME_HEADER)))
- {
- cc->txn_url = svn_path_url_add_component2(cc->ras->vtxn_stub,
- header_val, cc->pool);
- cc->txn_root_url
- = svn_path_url_add_component2(cc->ras->vtxn_root_stub,
- header_val, cc->pool);
- }
- else if ((header_val = ne_get_response_header(req->ne_req,
- SVN_DAV_TXN_NAME_HEADER)))
- {
- cc->txn_url = svn_path_url_add_component2(cc->ras->txn_stub,
- header_val, cc->pool);
- cc->txn_root_url = svn_path_url_add_component2(cc->ras->txn_root_stub,
- header_val, cc->pool);
+ err = svn_ra_neon__request_dispatch(NULL, req, NULL, "( create-txn )",
+ 201, 0, dir_pool);
+ if (!err)
+ {
+ /* Check the response headers for either the virtual transaction
+ details, or the real transaction details. We need to have
+ one or the other of those! */
+ if ((header_val = ne_get_response_header(req->ne_req,
+ SVN_DAV_VTXN_NAME_HEADER)))
+ {
+ cc->txn_url = svn_path_url_add_component2(cc->ras->vtxn_stub,
+ header_val, cc->pool);
+ cc->txn_root_url
+ = svn_path_url_add_component2(cc->ras->vtxn_root_stub,
+ header_val, cc->pool);
+ }
+ else if ((header_val
+ = ne_get_response_header(req->ne_req,
+ SVN_DAV_TXN_NAME_HEADER)))
+ {
+ cc->txn_url = svn_path_url_add_component2(cc->ras->txn_stub,
+ header_val, cc->pool);
+ cc->txn_root_url
+ = svn_path_url_add_component2(cc->ras->txn_root_stub,
+ header_val, cc->pool);
+ }
+ else
+ err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+ _("POST request did not return transaction "
+ "information"));
}
- else
- return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
- _("POST request did not return transaction "
- "information"));
+ svn_ra_neon__request_destroy(req);
+ SVN_ERR(err);
root->rsrc = NULL;
root->txn_root_url = svn_path_url_add_component2(cc->txn_root_url,
@@ -1570,6 +1577,7 @@ svn_error_t * svn_ra_neon__get_commit_ed
svn_delta_editor_t *commit_editor;
commit_ctx_t *cc;
apr_hash_index_t *hi;
+ const char *repos_root;
/* Build the main commit editor's baton. */
cc = apr_pcalloc(pool, sizeof(*cc));
@@ -1619,7 +1627,10 @@ svn_error_t * svn_ra_neon__get_commit_ed
*editor = commit_editor;
*edit_baton = cc;
+ SVN_ERR(svn_ra_neon__get_repos_root(session, &repos_root, pool));
+
SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
+ repos_root, cc->anchor_relpath,
ras->shim_callbacks, pool, pool));
return SVN_NO_ERROR;
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/fetch.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/fetch.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/fetch.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/fetch.c Wed May 16 20:32:43 2012
@@ -912,8 +912,19 @@ svn_error_t *svn_ra_neon__get_dir(svn_ra
final_url, SVN_RA_NEON__DEPTH_ONE,
NULL, which_props, pool));
- /* Count the number of path components in final_url. */
- final_url_n_components = svn_path_component_count(final_url);
+ /* In the loop below we will want to skip the effective '.' entry that
+ comes back from SVN_RA_NEON__DEPTH_ONE. To perform this skip we use
+ the component count of the FINAL_URL and compare it to the component
+ count of the keys in RESOURCES. But this only works if REVISION
+ was a valid revnum and FINAL_URL is a baseline collection (i.e. no
+ scheme://host prefix). If REVISION was SVN_INVALID_REVNUM then
+ FINAL_URL is a fully qualified URL, so we need to ignore the scheme
+ and host portions. */
+ if (SVN_IS_VALID_REVNUM(revision))
+ final_url_n_components = svn_path_component_count(final_url);
+ else
+ final_url_n_components = svn_path_component_count(
+ svn_path_url_add_component2(ras->root.path, path, pool));
/* Now we have a hash that maps a bunch of url children to resource
objects. Each resource object contains the properties of the
@@ -1818,6 +1829,10 @@ start_element(int *elem, void *userdata,
" element"));
svn_stringbuf_set(rb->namestr, name);
+ att = svn_xml_get_attr_value("rev", atts);
+ if (att) /* Not available on older repositories! */
+ crev = SVN_STR_TO_REV(att);
+
parent_dir = &TOP_DIR(rb);
/* Pool use is a little non-standard here. When lots of items in the
@@ -1832,8 +1847,8 @@ start_element(int *elem, void *userdata,
svn_path_add_component(pathbuf, rb->namestr->data);
SVN_ERR((*rb->editor->delete_entry)(pathbuf->data,
- SVN_INVALID_REVNUM,
- TOP_DIR(rb).baton,
+ crev,
+ parent_dir->baton,
subpool));
svn_pool_destroy(subpool);
break;
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/ra_neon.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/ra_neon.h Wed May 16 20:32:43 2012
@@ -1188,6 +1188,10 @@ svn_error_t *
svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
svn_delta_shim_callbacks_t *callbacks);
+svn_error_t *svn_ra_neon__get_repos_root(svn_ra_session_t *session,
+ const char **url,
+ apr_pool_t *pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/session.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/session.c Wed May 16 20:32:43 2012
@@ -1109,9 +1109,9 @@ static svn_error_t *svn_ra_neon__get_ses
return SVN_NO_ERROR;
}
-static svn_error_t *svn_ra_neon__get_repos_root(svn_ra_session_t *session,
- const char **url,
- apr_pool_t *pool)
+svn_error_t *svn_ra_neon__get_repos_root(svn_ra_session_t *session,
+ const char **url,
+ apr_pool_t *pool)
{
svn_ra_neon__session_t *ras = session->priv;
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/util.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_neon/util.c Wed May 16 20:32:43 2012
@@ -245,7 +245,15 @@ end_207_element(void *baton, int state,
case ELEM_responsedescription:
if (b->in_propstat)
- svn_stringbuf_set(b->propstat_description, b->cdata->data);
+ {
+ const char *data = b->cdata->data;
+
+ /* Remove leading newline added by DEBUG_CR on server */
+ if (*data == '\n')
+ ++data;
+
+ svn_stringbuf_set(b->propstat_description, data);
+ }
else
{
if (! svn_stringbuf_isempty(b->description))
Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/blame.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/blame.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_ra_serf/blame.c Wed May 16 20:32:43 2012
@@ -22,9 +22,6 @@
*/
#include <apr_uri.h>
-
-#include <expat.h>
-
#include <serf.h>
#include "svn_pools.h"
@@ -39,6 +36,8 @@
#include "svn_private_config.h"
+#include "private/svn_string_private.h"
+
#include "ra_serf.h"
#include "../libsvn_ra/ra_loader.h"
@@ -48,6 +47,7 @@
*/
typedef enum blame_state_e {
NONE = 0,
+ INITIAL = 0,
FILE_REVS_REPORT,
FILE_REV,
REV_PROP,
@@ -85,10 +85,7 @@ typedef struct blame_info_t {
/* The currently collected value as we build it up */
const char *prop_name;
- const char *prop_attr;
- apr_size_t prop_attr_len;
-
- svn_string_t *prop_string;
+ svn_stringbuf_t *prop_value;
/* Merged revision flag */
svn_boolean_t merged_revision;
@@ -113,6 +110,42 @@ typedef struct blame_context_t {
void *file_rev_baton;
} blame_context_t;
+
+#if 0
+/* ### we cannot use this yet since the CDATA is unbounded and cannot be
+ ### collected by the parsing context. we need a streamy mechanism for
+ ### this report. */
+
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t blame_ttable[] = {
+ { INITIAL, S_, "file-revs-report", FILE_REVS_REPORT,
+ FALSE, { NULL }, FALSE, FALSE },
+
+ { FILE_REVS_REPORT, S_, "file-rev", FILE_REV,
+ FALSE, { "path", "rev", NULL }, FALSE, TRUE },
+
+ { FILE_REV, D_, "rev-prop", REV_PROP,
+ TRUE, { "name", "?encoding", NULL }, FALSE, TRUE },
+
+ { FILE_REV, D_, "set-prop", SET_PROP,
+ TRUE, { "name", "?encoding", NULL }, FALSE, TRUE },
+
+ { FILE_REV, D_, "remove-prop", REMOVE_PROP,
+ FALSE, { "name", "?encoding", NULL }, FALSE, TRUE },
+
+ { FILE_REV, D_, "merged-revision", MERGED_REVISION,
+ FALSE, { NULL }, FALSE, FALSE },
+
+ { FILE_REV, D_, "txdelta", TXDELTA,
+ TRUE, { NULL }, FALSE, TRUE },
+
+ { 0 }
+};
+
+#endif
+
+
static blame_info_t *
push_state(svn_ra_serf__xml_parser_t *parser,
@@ -125,18 +158,16 @@ push_state(svn_ra_serf__xml_parser_t *pa
{
blame_info_t *info;
- info = apr_palloc(parser->state->pool, sizeof(*info));
+ info = apr_pcalloc(parser->state->pool, sizeof(*info));
info->pool = parser->state->pool;
info->rev = SVN_INVALID_REVNUM;
- info->path = NULL;
info->rev_props = apr_hash_make(info->pool);
info->prop_diffs = apr_array_make(info->pool, 0, sizeof(svn_prop_t));
- info->stream = NULL;
- info->merged_revision = FALSE;
+ info->prop_value = svn_stringbuf_create_empty(info->pool);
parser->state->private = info;
}
@@ -144,36 +175,31 @@ push_state(svn_ra_serf__xml_parser_t *pa
return parser->state->private;
}
+
static const svn_string_t *
create_propval(blame_info_t *info)
{
- const svn_string_t *s;
-
- if (!info->prop_attr)
- {
- return svn_string_create_empty(info->pool);
- }
- else
- {
- info->prop_attr = apr_pmemdup(info->pool, info->prop_attr,
- info->prop_attr_len + 1);
- }
-
- s = svn_string_ncreate(info->prop_attr, info->prop_attr_len, info->pool);
if (info->prop_base64)
{
- s = svn_base64_decode_string(s, info->pool);
+ const svn_string_t *morph;
+
+ morph = svn_stringbuf__morph_into_string(info->prop_value);
+#ifdef SVN_DEBUG
+ info->prop_value = NULL; /* morph killed the stringbuf. */
+#endif
+ return svn_base64_decode_string(morph, info->pool);
}
- return s;
+
+ return svn_string_create_from_buf(info->prop_value, info->pool);
}
static svn_error_t *
start_blame(svn_ra_serf__xml_parser_t *parser,
- void *userData,
svn_ra_serf__dav_props_t name,
- const char **attrs)
+ const char **attrs,
+ apr_pool_t *scratch_pool)
{
- blame_context_t *blame_ctx = userData;
+ blame_context_t *blame_ctx = parser->user_data;
blame_state_e state;
state = parser->state->current_state;
@@ -240,8 +266,7 @@ start_blame(svn_ra_serf__xml_parser_t *p
case REMOVE_PROP:
info->prop_name = apr_pstrdup(info->pool,
svn_xml_get_attr_value("name", attrs));
- info->prop_attr = NULL;
- info->prop_attr_len = 0;
+ svn_stringbuf_setempty(info->prop_value);
enc = svn_xml_get_attr_value("encoding", attrs);
if (enc && strcmp(enc, "base64") == 0)
@@ -266,10 +291,10 @@ start_blame(svn_ra_serf__xml_parser_t *p
static svn_error_t *
end_blame(svn_ra_serf__xml_parser_t *parser,
- void *userData,
- svn_ra_serf__dav_props_t name)
+ svn_ra_serf__dav_props_t name,
+ apr_pool_t *scratch_pool)
{
- blame_context_t *blame_ctx = userData;
+ blame_context_t *blame_ctx = parser->user_data;
blame_state_e state;
blame_info_t *info;
@@ -338,11 +363,11 @@ end_blame(svn_ra_serf__xml_parser_t *par
static svn_error_t *
cdata_blame(svn_ra_serf__xml_parser_t *parser,
- void *userData,
const char *data,
- apr_size_t len)
+ apr_size_t len,
+ apr_pool_t *scratch_pool)
{
- blame_context_t *blame_ctx = userData;
+ blame_context_t *blame_ctx = parser->user_data;
blame_state_e state;
blame_info_t *info;
@@ -360,8 +385,7 @@ cdata_blame(svn_ra_serf__xml_parser_t *p
{
case REV_PROP:
case SET_PROP:
- svn_ra_serf__expand_string(&info->prop_attr, &info->prop_attr_len,
- data, len, parser->state->pool);
+ svn_stringbuf_appendbytes(info->prop_value, data, len);
break;
case TXDELTA:
if (info->stream)
@@ -437,8 +461,7 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
svn_ra_serf__session_t *session = ra_session->priv;
svn_ra_serf__handler_t *handler;
svn_ra_serf__xml_parser_t *parser_ctx;
- const char *relative_url, *basecoll_url, *req_url;
- int status_code;
+ const char *req_url;
svn_error_t *err;
blame_ctx = apr_pcalloc(pool, sizeof(*blame_ctx));
@@ -451,13 +474,14 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
blame_ctx->include_merged_revisions = include_merged_revisions;
blame_ctx->done = FALSE;
- SVN_ERR(svn_ra_serf__get_baseline_info(&basecoll_url, &relative_url, session,
- NULL, session->session_url.path,
- end, NULL, pool));
- req_url = svn_path_url_add_component2(basecoll_url, relative_url, pool);
+ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */,
+ session, NULL /* conn */,
+ NULL /* url */, end,
+ pool, pool));
handler = apr_pcalloc(pool, sizeof(*handler));
+ handler->handler_pool = pool;
handler->method = "REPORT";
handler->path = req_url;
handler->body_type = "text/xml";
@@ -474,7 +498,6 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
parser_ctx->end = end_blame;
parser_ctx->cdata = cdata_blame;
parser_ctx->done = &blame_ctx->done;
- parser_ctx->status_code = &status_code;
handler->response_handler = svn_ra_serf__handle_xml_parser;
handler->response_baton = parser_ctx;
@@ -484,9 +507,9 @@ svn_ra_serf__get_file_revs(svn_ra_sessio
err = svn_ra_serf__context_run_wait(&blame_ctx->done, session, pool);
err = svn_error_compose_create(
- svn_ra_serf__error_on_status(status_code,
+ svn_ra_serf__error_on_status(handler->sline.code,
handler->path,
- parser_ctx->location),
+ handler->location),
err);
return svn_error_trace(err);